function table_changer(default_name)
{
  if(!isset(default_name)) default_name = 'default';

  if(!is_string(default_name) || strlen(default_name)===0) return null;

  this.default_name = default_name;

  this.tab_list = [];
  this.is_debug = true;

  this.default_pack = table_changer_default_pack;

  this.default_on = table_changer_default_on;
  this.default_off = table_changer_default_off;

  this.on_change = table_changer_on_change;

  this.add_table = table_changer_add_table;

  this.toggle2key = table_changer_toggle2key;

  this.init = table_changer_init;
  this.get_table_by_state = table_changer_get_table_by_state;

  return this;
}

function table_changer_init()
{
  return this.toggle2key(this.get_table_by_state(true));
}

function table_changer_get_table_by_state(state)
{
  if(!isset(state)) state = false;

  if(!is_bool(state)) return [];

  var rc = [];

  for(i in this.tab_list)
  {
    if(i !== this.default_name &&
       this.tab_list[i].state === state) rc[rc.length] = i;
  }

  return rc;
}

function table_changer_default_pack()
{
  return {state: false, sub_keys: [], tables: [], at_on: [], at_off: []};
}

function table_changer_default_on(attr, value)
{
  return this.on_change(this.default_name, true, attr, value);
}

function table_changer_default_off(attr, value)
{
  return this.on_change(this.default_name, false, attr, value);
}

function table_changer_on_change(key, is_on, attr, value)
{
  if(!is_string(key) || strlen(key)===0 ||
     !is_bool(is_on) ||
     !is_string(attr) || strlen(attr)===0 ||
     !isset(value)) return false;

  if(!array_key_exists(key, this.tab_list))
    this.tab_list[key] = this.default_pack();

  var cur_tab = this.tab_list[key];

  if(is_on) cur_tab.at_on[attr] = value;
  else cur_tab.at_off[attr] = value;

  return true;
}

function table_changer_add_table(key, table, state, sub_keys)
{
  if(!is_string(key) || strlen(key)===0 ||
     !is_bool(state)) return false;

  if(!is_string(table) && !is_array(table)) return false;

  if(is_string(table)) table = [table];

  if(!isset(sub_keys)) sub_keys = [];

  if(is_string(sub_keys)) sub_keys = [sub_keys];

  if(!array_key_exists(key, this.tab_list))
    this.tab_list[key] = this.default_pack();

  var cur_tab = this.tab_list[key];

  cur_tab.state = state;
  cur_tab.tables = table;

  cur_tab.sub_keys = sub_keys;

  return true;
}

function table_changer_toggle2key(keys)
{
  if(is_string(keys) && strlen(keys)===0) return false;

  if(is_string(keys)) keys = [keys];

  var i, j, k;
  var cur_tab;
  var attr;

  var obj = null;

  var to_eval = '';

  var sub_keys = [];

  for(i in this.tab_list)
  {
    if(i === this.default_name) continue;

    //alert('cur_tab: ' + i);

    cur_tab = this.tab_list[i];

    cur_tab.state = in_array(i, keys);

    for(j in cur_tab.tables)
    {
      obj = document.getElementById(cur_tab.tables[j]);

      if(!obj) continue;

      obj.style.display = (cur_tab.state) ?  '' : 'none';
    }

    sub_keys = array_merge([i], cur_tab.sub_keys);

    for(k in sub_keys)
    {
      obj = document.getElementById(sub_keys[k]);

      if(!obj) {if(this.is_debug){alert('sub_keys: ' + sub_keys[k]);} continue;}

      attr = (cur_tab.state ? cur_tab.at_on : cur_tab.at_off);

      for(j in attr)
      {
        to_eval = 'obj.'+j+' = attr[j];';

        try {
          eval(to_eval);
        } catch(no_eval) {if(this.is_debug){alert(to_eval);}}
      }

      if(!array_key_exists(this.default_name, this.tab_list)) continue;

      attr = (cur_tab.state ? this.tab_list[this.default_name].at_on : this.tab_list[this.default_name].at_off);

      //alert(attr);

      for(j in attr)
      {
        to_eval = 'obj.'+j+' = attr[j];';

        //alert(to_eval);

        try {
          eval(to_eval);
        } catch(no_eval) {if(this.is_debug){alert(to_eval);}}
      }
    }
  }

  //alert('ok');

  return true;
}

function output_window(name, location)
{
  if(!is_string(name)) name = 'output_window';
  if(!is_string(location) || strlen(location)===0) location = 'about:blank';

  this.win = null;
  this.docWritable = false;
  this.name = name;
  this.location = location;

  this.bodyID = 'bodyID';

  this.attrib = {common: {dependent: true, resizable: false, status: false},
                 win_size: {height: -1, width: -1},
                 win_pos: {left: -1, top: -1},
                 win_bar: {menubar: false, toolbar: false}};

  this.setName = output_window_setName;
  this.isOpen = output_window_isOpen;
  this.open = output_window_open;
  this.close = output_window_close;
  this.stop = output_window_stop;
  this.focus = output_window_focus;

  this.setCommon = output_window_setCommon;

  this.setWinSize = output_window_setWinSize;
  this.setWinPos = output_window_setWinPos;
  this.setWinBar = output_window_setWinBar;

  this.bool2attrib = output_window_bool2attrib;
  this.genAttrib = output_window_genAttrib;

  this.docOpen = output_window_docOpen;
  this.docClose = output_window_docClose;

  this.writeStatus = output_window_writeStatus;
  this.writeText = output_window_writeText;

  //this. = output_window_;

  return this;
}

function output_window_setName(name)
{
  if(!is_string(name)) return false;

  this.name = name;

  if(this.isOpen()) this.win.name = this.name;

  return true;
}

function output_window_isOpen()
{
  return (!is_null(this.win) && !this.win.closed);
}

function output_window_stop()
{
  if(!this.isOpen()) return false;

  this.win.stop();

  return true;
}

function output_window_open(focusIt)
{
  if(strlen(this.location)===0) return false;

  if(!is_bool(focusIt)) focusIt = false;

  var attrib = '', tmp = '';

  for(var i in this.attrib)
  {
    tmp = this.genAttrib(this.attrib[i]);

    if(strlen(tmp)===0) continue;

    if(strlen(attrib) > 0) attrib += ',';

    attrib += tmp;
  }

  if(this.isOpen()) this.close();

  this.win = window.open(this.location, this.name, attrib);

  if(focusIt) this.focus();

  return is_object(this.win);
}

function output_window_bool2attrib(value)
{
  return (is_bool(value) && value ? 'yes' : 'no');
}

function output_window_genAttrib(obj)
{
  if(!is_array(obj) && !is_object(obj)) return '';

  var attr = '';
  var isFirst = true;

  for(var i in obj)
  {
    if(is_number(obj[i]) && obj[i] === -1) continue;

    if(isFirst) isFirst = false;
    else attr += ',';

    attr += i + '=' + (is_bool(obj[i]) ? this.bool2attrib(obj[i]) : obj[i]);
  }

  return attr;
}

function output_window_close()
{
  if(!this.isOpen()) return true;

  if(this.docWritable) this.docClose();

  this.win.close();

  return true;
}

function output_window_docOpen()
{
  if(!this.isOpen()) return false;

  if(this.docWritable) return true;

  this.win.document.open();

  this.docWritable = true;

  return true;
}

function output_window_docClose()
{
  if(!this.isOpen()) return false;

  if(!this.docWritable) return true;

  this.win.document.close();

  this.docWritable = false;

  return true;
}


function output_window_focus()
{
  if(!this.isOpen()) return false;

  this.win.focus();

  return true;
}

function output_window_setWinSize(height, width)
{
  if(!is_number(height) || !is_number(width)) return false;

  if(height < -1 || height === 0 ||
     width < -1 || width === 0
    ) return false;

  this.attrib.win_size.height = height;
  this.attrib.win_size.width = width;

  if(!this.isOpen()) return true;

  if(this.attrib.win_size.height !== -1) this.win.outerHeight = this.attrib.win_size.height;
  if(this.attrib.win_size.width !== -1) this.win.outerWidth = this.attrib.win_size.width;

  return true;
}


function output_window_setWinPos(left, top)
{
  if(!is_number(left) || !is_number(top)) return false;

  if(left < -1 || left === 0 ||
     top < -1 || top === 0
    ) return false;

  this.attrib.win_pos.left = left;
  this.attrib.win_pos.top = top;

  if(!this.isOpen()) return true;

  if(this.attrib.win_pos.left !== -1) this.win.pageXOffset = this.attrib.win_pos.left;
  if(this.attrib.win_pos.top !== -1) this.win.pageYOffset = this.attrib.win_pos.top;

  return true;
}

function output_window_setWinBar(menubar, toolbar)
{
  if(!is_bool(menubar) || !is_bool(toolbar)) return false;

  this.attrib.win_bar.menubar = menubar;
  this.attrib.win_bar.toolbar = toolbar;

  if(!this.isOpen()) return true;

  if(this.win.menubar) this.win.menubar.visible = this.attrib.win_bar.menubar;
  if(this.win.toolbar) this.win.toolbar.visible = this.attrib.win_bar.toolbar;

  return true;
}

function output_window_setCommon(dependent, resizable, status)
{
  if(!is_bool(dependent) || !is_bool(resizable) || !is_bool(status)) return false;

  this.attrib.common.dependent = dependent;
  this.attrib.common.resizable = resizable;
  this.attrib.common.status = status;

  if(!this.isOpen()) return true;

  if(this.win.statusbar) this.win.statusbar.visible = this.attrib.common.status;

  return true;
}

function output_window_writeStatus(msg)
{
  if(!this.isOpen() || !isset(msg) || !this.attrib.common.status) return false;

  this.win.status = msg;

  return true;
}

function output_window_writeText(msg, newline)
{
  if(!this.isOpen() || !isset(msg)) return false;

  if(!is_bool(newline)) newline = false;

  /*var nextText = this.win.document.createTextNode(msg + (newline ? '<BR>' : ''));

  alert(nextText);

  alert(this.bodyID);

  this.win.document.getElementById(this.bodyID).appendChild(nextText);*/

  //alert(this.win.document.getElementsByTagName("body")[0].text);

  //this.win.document.write(msg + (newline ? '\n\r' : ''));

  /*var to_write = '<html><head><title>test</title></head><body>' + msg + '</body></html>';

  this.win.document.write(to_write);*/

  var not_open = !this.docWritable;

  if(not_open) this.docOpen();

  this.win.document.write(msg + (newline ? '<BR>\n\r' : ''));

  if(not_open) this.docClose();

  return true;
}


/*
  this.attrib = {common: {dependent: true, resizable: false, status: false},
                 win_size: {height: -1, width: -1},
                 win_pos: {left: -1, top: -1},
                 win_bar: {menubar: false, toolbar: false}};


*/
