<?xml version="1.0" encoding="UTF-8"?>

<!-- Copyright 2009 Google Inc. -->
<!-- All Rights Reserved -->

<Module>
<ModulePrefs
  title="Chat Interpreter">
  <Require feature="rpc"/>
  <Require feature="google.sharedstate"/>
</ModulePrefs>
<Content type="html">
<![CDATA[
<style>
body {
  font-family: Arial, sans-serif;
  font-size: 62.5%;
  margin: 4px;
  overflow: hidden;
}

#log {
  overflow: auto;
  background-color: #ebeff9;
  height: 159px;
}

#input {
  height: 32px;
  width: 100%;
  padding: 4px;
  margin-top: 4px;
  border: 2px solid orange;
  font-size: 1.6em;
}

.entry {
  border-top: 1px solid #f2f8ff;
  border-bottom: 1px solid #b0bbc0;
  background-color: #c2cff1;
  font-size: 1.3em;
  padding: 2px 4px;
}

.mine {
  border-top: 1px solid #fff !important;
  border-bottom: 1px solid #ccc !important;
  background-color: #eee !important;
}

.cmd {
  border-top: 1px solid #cfa !important;
  border-bottom: 1px solid #9b8 !important;
  background-color: #ac9 !important;
}

.translation, .ok, .error {
  background-color: #ffffcc;
  margin: 2px;
  padding: 2px 4px;
  color: #666;
  font-style: italic;
  font-size: 1em;
}

.ok {
  background-color: #ffffff;
  color: #363 !important;
}

.error {
  background-color: #ffffff;
  color: #f66 !important;
}

.lang {
  font-style: normal;
  font-weight: bold;
}
</style>

<div id="log"></div>

<div>
<input id="input" type="text"/>
</div>

<script src="http://www.google.com/jsapi"></script>
<script>
// Initializes Google Translation API
google.load("language", "1");

// My id
var me;

// Preferred language
var myLang = (new gadgets.Prefs()).getLang();

// Dummy sender id for commands
var myCmd = '!';

// Sequential id for chat entries
var entryId = 0;

function $(id) {
  return document.getElementById(id);
}

function log() {
  return $('log');
}

function input() {
  return $('input');
}

function updateLayout() {
  var h = document.body.clientHeight - 64;
  log().style.height = h + 'px';
  scrollToBottom();
}

function scrollToBottom() {
  var el = log();
  el.scrollTop = el.scrollHeight - el.offsetTop;
}

function htmlEscape(s) {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').
      replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

function addEntry(entry, sender) {
  var html = '<div id="entry' + ++entryId +
      '" class="entry' + (sender == me ? ' mine' : sender == myCmd ? ' cmd' : '') +
      '">' + htmlEscape(entry) + '</div>';
  log().innerHTML += html;
  scrollToBottom();

  if (sender == myCmd) {
    executeCommand(entry.substr(1), entryId);
  } else if (google.language && sender != me) {
    translateEntry(entry, entryId);
  }
}

function completeCommand(message, id, className) {
  var el = $('entry' + id);
  if (el) {
    el.innerHTML += '<div class="' + className + '">' + message + '</div>';
    scrollToBottom();
  }
}

function executeCommand(entry, id) {
  if (entry == 'clear') {
    // Clears the chat log
    log().innerHTML = '';
  } else if (entry == 'lang') {
    // Displays the preferred language
    var html = 'Preferred language: <span class="lang">[' + myLang + ']</span>';
    completeCommand(html, id, 'ok');
  } else if (entry.substr(0, 5) == 'lang=') {
    // Changes the preferred language
    var langCode = entry.substr(5);
    if (langCode) {
      for (var l in google.language.Languages) {
        if (google.language.Languages[l] == langCode) {
          myLang = langCode;
          completeCommand('Preferred language changed to: <span class="lang">[' +
              langCode + ']</span> ' + l, id, 'ok');
          return;
        }
      }
    }
    completeCommand('Unrecognized language code.', id, 'error');
  } else {
    completeCommand('Unrecognized command.', id, 'error'); 
  }
}

function translateEntry(entry, id) {
  google.language.translate(entry, '', myLang, function(res) {
    if (!res.error && res.detectedSourceLanguage != myLang && $('entry' + id)) {
      $('entry' + id).innerHTML += '<div class="translation">' +
          '<span class="lang">[' + res.detectedSourceLanguage +
          ']</span> ' + htmlEscape(res.translation) + '</div>';
      scrollToBottom();
    }
  });
}

function sendEntry(entry) {
  // Full chat log is not stored in the shared state. This is intentional.
  gadgets.sharedstate.updateState({
    sender: me,
    entry: entry
  });
}

function onKeyPress(e) {
  if (!e) {
    e = window.event;
  }

  if (e.keyCode == 13) {
    var entry = input().value;
    if (entry) {
      input().value = '';
      if (entry[0] == '/') {
        // Processes it as a command
        addEntry(entry, myCmd);
      } else {
        // Treats it as a message and broadcasts it
        addEntry(entry, me);
        sendEntry(entry);
      }
    }
  }
}

function onStateChange(state) {
  if (typeof state == 'object' && state.sender != me && state.entry) {
    addEntry(state.entry, state.sender);
  }
}

function initRTC(myId, otherIds) {
  me = myId;
  // Samples
  input().value = myId < otherIds[0] ? 'Bonjour! Comment \u00e7a va?' :
      '\u4f60\u53ef\u660e\u767d\u6211\u5728\u8bf4\u4ec0\u4e48\uff1f';
}

function init() {
  updateLayout();
  input().focus();
  input().onkeypress = onKeyPress;
  window.onresize = updateLayout;
}

gadgets.util.registerOnLoadHandler(init);
gadgets.sharedstate.initialize(initRTC);
gadgets.sharedstate.setStateChangeHandler(onStateChange);
</script>
]]>
</Content>
</Module>
