var formulaSwfVer = 4;

var isFormulaInited = {};
var isFormulaHiding = {};

var curFormulaId;
var curContainerId;
var curTalkId;

var formulaToShow;
var containerToShow;
var talkToStart;
var alignToSet;

var isDebug = (location.hostname.indexOf('new') == 0);

function showFormula(id, containerId, talkId, align) {
//log('showFormula(' + containerId + '), curContainerId: ' + curContainerId + ', formulaObject: ' + getElInfo(getFormulaObject(curContainerId)) + ', inited[cur]: ' + isFormulaInited[curContainerId] + ', hid[cur]: ' + isFormulaHiding[curContainerId]);
  containerId = (containerId || id);
  if (containerId != curContainerId && curContainerId) {
    var processContainer = true;
    var formulaObject = getFormulaObject(curContainerId);
    if (formulaObject) {
      if (isFormulaInited[curContainerId]) {
        if (!isFormulaHiding[curContainerId]) {
          isFormulaHiding[curContainerId] = true;
          formulaObject.hideFormula();
//        log('hideFormula()');
        }
        processContainer = false;
      } else {
//      удалить из контейнера
        var p = formulaObject.parentNode;
        while (p.firstChild) p.removeChild(p.firstChild);
        p.style.display = 'none';
        var container = $(curContainerId + '-nav');
        if (container) container.style.display = 'none';
      }
    }
    if (processContainer) {
      container = $('un-' + curContainerId);
//    if (можно гасить буквы && ещё не показали) {
      if (container && (container.offsetHeight == 0 || container.isZooming)) {
        if (container.offsetHeight == 0) container.style.display = 'block';
        startZoom(container, 'on', (container.isZooming ? 'zooming ' + container.isZooming : 'container hidden'));
      } else {
//      переключить контейнеры
        if (container) container.style.display = 'block';
        container = $(curContainerId);
        if (container) container.style.display = 'none';
        container = $(curContainerId + '-nav');
        if (container) container.style.display = 'none';
      }
    }
//  обнулить старые переменные
    curFormulaId = null;
    curContainerId = null;
    curTalkId = null;
  }

  if (!containerId) return;
  curContainerId = containerId;
  var formulaObject = getFormulaObject(containerId);
  if (!formulaObject) {
    formulaToShow = id;
    containerToShow = containerId;
    talkToStart = talkId;
    alignToSet = align;
    container = $('un-' + containerId);
//  if (можно гасить буквы && ещё не загасили) {
    if (container && container.offsetHeight > 0) {
//    начать гасить буквы, чтоб потом создать объект и показать формулу
      addClass(container, 'zoom');
      startZoom(container, 'off');
//    curContainerId = containerId;
    } else {
//    создать объект, потом начать показывать формулу
      createSwfObject(containerId, align);
    }
  } else {
//  curContainerId = containerId;
    if (!isFormulaInited[containerId]) {
      formulaToShow = id;
      containerToShow = containerId;
      talkToStart = talkId;
    } else {
      if (id != curFormulaId) {
        curFormulaId = id;
        isFormulaHiding[containerId] = false;
        try {
          formulaObject.showFormula(id, '', align, talkId, '');
//        log('showFormula(' + id + ')');
        } catch(err) {
          throw new Error('showFormula() Error: inited[' + containerId + ']: ' + isFormulaInited[containerId] + ', ' + err + ', id: ' + id + ', formulaObject: ' + getElInfo(formulaObject));
        }
      } else {
        if (talkId != curTalkId) {
          curTalkId = talkId;
          try {
            formulaObject.startTalk(talkId);
          } catch(err) {
            throw new Error('startTalk() Error: inited[' + containerId + ']: ' + isFormulaInited[containerId] + ', ' + err + ', id: ' + id + ', talkId: ' + talkId + ', formulaObject: ' + getElInfo(formulaObject));
          }
        }
      }
    }
  }
}

function hideCurFormula() {
  showFormula(null);
}

function startZoom(container, dir, from) {
//log('startZoom' + (dir == 'on' ? 'On' : 'Off') + '(' + getElInfo(container) + (from ? ', ' + from : '') + ')');
  if (!container.absBlocks) setAbsBlocks(container);
  else if (container.zoomIntervalId) clearInterval(container.zoomIntervalId);
  container.isZooming = dir;
  container.zoomIntervalId = setInterval(function() { zoomIteration(container, dir) }, 20);
}

function zoomIteration(container, dir) {
  var zoomingOff = (dir == 'off');
  var prevIdx = (container.zoomIdx != null ? container.zoomIdx : 14);
  var idx = container.zoomIdx = 
    (container.zoomIdx != null ? container.zoomIdx + (zoomingOff ? -1 : +1) : 13);
//log('zoomClass: ' + container.className + ', old: ' + prevIdx + ', new: ' + idx);
  replaceClass(container, 'ts' + prevIdx, 'ts' + idx);
//var absBlocks = container.absBlocks;
//for (var i = 0, len = absBlocks.length; i < len; i++) {
//  absBlocks[i].style.fontSize = idx + 'px';
//}
  if (zoomingOff) {
    if (idx <= 0) {
      clearInterval(container.zoomIntervalId);
      container.zoomIntervalId = null;
      container.isZooming = null;
      afterZoomOff(container);
    }
  } else {
    if (idx >= 14) {
      clearInterval(container.zoomIntervalId);
      container.zoomIntervalId = null;
      container.isZooming = null;
      removeClass(container, 'ts' + container.zoomIdx);
      afterZoomOn(container);
    }
  }
}

function afterZoomOn(container) {
//log('afterZoomOn(' + getElInfo(container) + ')');
  if (container) removeClass(container, 'zoom');
  else throw new Error('afterZoomOn: container = ' + getElInfo(container));
}

function afterZoomOff(container) {
//log('afterZoomOff(' + getElInfo(container) + ')');
  container.style.display = 'none';
  if (containerToShow) createSwfObject(containerToShow, alignToSet);
}

function setAbsBlocks(container) {
  container.innerHTML = htmlToEms(container.innerHTML);
  var ems = container.getElementsByTagName('EM');
  var absBlocks = [];
  for (var i = 0, len = ems.length; i < len; i++) {
    var em = ems[i];
    var block = document.createElement('SPAN');
    block.innerHTML = em.innerHTML;
    em.insertBefore(block, em.firstChild);
    absBlocks.push(block);
  }
  container.absBlocks = absBlocks;
}

function htmlToEms(text) {
  var res = '';
  for (var i = 0, len = text.length; i < len; i++) {
    var c = text.charAt(i);
    switch (c) {
      case '<':
        do {
          res += c;
          c = text.charAt(++i);
        } while (c != '>');
        res += c;
        break;

      case '&':
        do {
          res += c;
          c = text.charAt(++i);
        } while (c != ';');
        res += c;
        break;
      
      case ' ':
      case '\n':
        res += c;
        break;

      default:
        res += '<em>' + c + '</em>';
        break;
    }
  }
  return res;
}

function getFormulaObject(id) {
  return $('formula-' + id);
}

function createSwfObject(id, align) {
  if (!formulaSwfVer) formulaSwfVer = Math.floor(Math.random()*100000);
  var sesNum = getCookieValue('sesNum');
  if (sesNum == null) {
    sesNum = Math.round(1000000000*Math.random());
    setCookieValue('sesNum', sesNum, 'session')
  }
  var container = $(id);
  if (!container) throw String('Flash container not found: "' + id + '"');
  var so = new SWFObject('/fe/formula' + (isDebug ? '_debug' : '') + '.swf?' + formulaSwfVer, 'formula-' + id, '100%', '100%', '9');
  so.addParam('scale', 'noscale');
  so.addParam('salign', 'tl');
  so.addParam('wmode', 'transparent');
  so.addVariable('id', id);
  so.addVariable('xmlDir', '/fe/');
  so.addVariable('align', align || '');
  so.addVariable('sesNum', sesNum);
  so.write(id);
  
  container.style.display = 'block';

  container = $(id + '-nav');
  if (container) container.style.display = 'block';

  var flashObj = $('formula-' + id);
  if (flashObj) setupEvent(flashObj, 'mouseout', mouseOutFlash);
  
  isFormulaInited[id] = false;
  talkStateChanged(id, 'stopped');
  curFormulaId = null;
  curTalkId = null;
}

function mouseOutFlash(event) {
  var el = event.target || event.fromElement;
//log('mouse out flash, event.target: ' + el + (el ? ' ' + el.tagName + (el.id ? '#' + el.id : '') : ''));
}

function formulaInited(id) {
  setTimeout(function() { startFormulaActions(id) }, 0);
}

function startFormulaActions(id) {
  if (id != containerToShow) return;
  isFormulaInited[id] = true;
  if (formulaToShow) {
    var f = formulaToShow;
    var c = containerToShow;
    var t = talkToStart;
    var a = alignToSet;
    formulaToShow = null;
    containerToShow = null;
    talkToStart = null;
    alignToSet = null;
    showFormula(f, c, t, a);
  } else if (talkToStart) {
    var t = talkToStart;
    talkToStart = null;
    startTalk(t);
  }
}

function formulaHiddenHandler(id) {
  setTimeout(function() { removeFormulaAndZoom(id) }, 0);
}

function removeFormulaAndZoom(id) {
  if (!isFormulaHiding[id]) return;
  isFormulaHiding[id] = false;
  isFormulaInited[id] = false;
  var container = $(id);
  if (container) {
    container.innerHTML = '';
    container.style.display = 'none';
  }
  container = $(id + '-nav');
  if (container) container.style.display = 'none';
  container = $('un-' + id);
  if (container && (container.offsetHeight == 0 || container.isZooming)) {
    if (container.offsetHeight == 0) container.style.display = 'block';
    startZoom(container, 'on', 'after hide');
  }
}



function showLogoFormula(talkId) {
//hideLabels();
  showFormula('logo', 'formula-logo', talkId, 'tl');
}



function startTalk(id) {
  if (id != curContainerId) return;
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id] && !isFormulaHiding[id]) {
    formulaObject.startTalk(id);
  } else {
    talkToStart = id;
  }
}

function playTalk(id) {
  if (id != curContainerId) return;
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id] && !isFormulaHiding[id]) {
    if (talkState == 'stopped') {
      formulaObject.startTalk(id);
    } else if (talkState == 'playing') {
      formulaObject.pauseTalk();
    } else if (talkState == 'paused') {
      formulaObject.continueTalk();
    }
  } else {
    talkToStart = id;
  }
}

function goPrev() {
  var id = curContainerId;
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id] && !isFormulaHiding[id]) {
    formulaObject.showPrevPhrase();
  }
}

function goNext() {
  var id = curContainerId;
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id] && !isFormulaHiding[id]) {
    formulaObject.showNextPhrase();
  }
}

function goNextAndPlay() {
  var id = curContainerId;
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id] && !isFormulaHiding[id] && talkState == 'paused') {
    formulaObject.continueTalk();
  }
}

function bubbleMovieFinished(id) {
  setTimeout(function() { notifyClipFinished(id) }, 0);
}

function notifyClipFinished(id) {
  var formulaObject = getFormulaObject(id);
  if (formulaObject && isFormulaInited[id]) formulaObject.screenClipFinished();
}

function talkStateChanged(id, state) {
  log('state(' + id + ') = ' + state + (id != curContainerId || !curContainerId ? '' : ' - set'));
  if (id != curContainerId || !curContainerId) return;
  talkState = state;
  var navPanel = $(curContainerId + '-nav');
  if (navPanel)
    if (talkState == 'playing') addClass(navPanel, 'play'); else removeClass(navPanel, 'play');
  if (isDebug) document.title = curContainerId + ' - ' + talkState;
//var nextBtn = $(curContainerId + '-next');
//if (nextBtn) nextBtn.src = (talkState == 'playing' ? '/i/next-on.gif' : '/i/next.gif');
}


var
  userAgent = navigator.userAgent,
  isKHTML = (userAgent.indexOf('KHTML') >= 0),
  isOpera = (userAgent.indexOf('Opera') >= 0),
  isIE = (!isOpera && userAgent.indexOf('MSIE') >= 0),
  isIE50 = (isIE && /MSIE 5\.0/.test(userAgent) && navigator.platform == 'Win32'),
  isMozilla = (!isKHTML && !isOpera &&  userAgent.indexOf('Gecko') >= 0);

function $(id) { return (typeof(id) == 'string' ? document.getElementById(id) : id) }

function indexOfItem(array, item) {
  for (var i = 0, len = array.length; i < len; i++) {
    if (array[i] === item) return i;
  }
  return -1;
}

function addClass(block, className) {
  var c = block.className.split(' ');
  if (indexOfItem(c, className) < 0) {
    c.push(className);
    block.className = c.join(' ');
  }
}

function removeClass(block, className) {
  var c = block.className.split(' ');
  var i = indexOfItem(c, className);
  if (i >= 0) {
    c.splice(i, 1);
    block.className = c.join(' ');
  }
}

function replaceClass(block, oldClass, newClass) {
  var c = block.className.split(' ');
  var i = indexOfItem(c, oldClass);
  if (i >= 0) c.splice(i, 1);
  if (indexOfItem(c, newClass) < 0) c.push(newClass);
  block.className = c.join(' ');
}

function incCookie(name) {
  var num = parseInt(getCookieValue(name));
  num = (isNaN(num) ? 1 : (num + 1) % 10);
  setCookieValue(name, num);
  return num;
}

function getCookieValue(name) {
  name = name.toLowerCase();
  var cookies = document.cookie.split(';');
  for (var i = 0, l = cookies.length; i < l; i++) {
    if (cookies[i].match(/^\s?(.*?)\=(.*)/)) {
      var n = RegExp.$1.toLowerCase();
      if (n == name) return RegExp.$2;
    }
  }
  return null;
}

function setCookieValue(name, value, date) {
  var d = null;
  if (date != 'session') {
    d = new Date();
    d.setFullYear(d.getFullYear() + (date || 1));
  }
  var s = name+'='+value + '; path=/; domain=.' + location.hostname + (d ? '; expires='+d.toUTCString() : '');
  document.cookie = s;
}

function setupEvent(el, eventType, handler, capture) {
  if (el.attachEvent) el.attachEvent('on'+eventType, handler)
  else if (el.addEventListener) el.addEventListener(eventType, handler, capture);
}

function removeEvent(el, eventType, handler, capture) {
  if (el.detachEvent) el.detachEvent('on'+eventType, handler)
  else if (el.removeEventListener) el.removeEventListener(eventType, handler, capture);
}

function getElInfo(el) {
  if (!el) return 'null';
  return (el.tagName ? el.tagName + (el.id ? '#' + el.id : '') + (el.className ? '.' + el.className : '') : el);
}


function setLinkBG(id) {
  if (isIE) {
    var link = $(id);
    if (link) {
      link.style.backgroundColor = '#FFFFFF';
      link.style.filter = 'alpha(opacity=0)';
    }
  }
}


function log(s) {
  if (!isDebug) return;
  var logBlock = window.logBlock;
  if (!logBlock) {
    logBlock = window.logBlock = document.createElement('div');
    logBlock.style.padding = '1em';
    logBlock.style.backgroundColor = '#FFFFFF';
//  if ('filter' in logBlock.style)
//    logBlock.style.filter = 'alpha(opacity=50)';
//  else
//    logBlock.style.opacity = 0.5;
    logBlock.style.border = '1px solid gray';
    logBlock.style.position = 'absolute';
    logBlock.style.top = '1em';
    document.body.appendChild(logBlock);
  }
  logBlock.innerHTML += s + '<br>';
  logBlock.style.left = (document.body.offsetWidth - logBlock.offsetWidth - 16) + 'px';
}
