var smiles = new Array("-100-", "-101-", "-102-", "-103-", "-104-", "-105-", "-106-", "-107-", "-108-", "-109-", "-110-", "-111-",
                       "-112-", "-113-", "-114-", "-115-", "-116-", "-117-", "-118-", "-119-", "-120-", "-121-",
                       "-122-", "-123-", "-124-", "-125-", "-126-", "-127-", "-128-", "-129-", "-130-", "-131-", "-132-", "-133-",
                       "-134-", "-135-", "-136-", "-137-", "-138-", "-139-", "-140-", "-141-", "-142-", "-143-", "-144-", "-145-", "-146-");
var roomTimeout = null;
var rooms = new Array();
var currentRoomId = 0;
var currentRoomColor = '';

var msgTimeout = null;
var lastMsgId = 0;
var sid = '';
var scrolling = 0;
var messages = new CircularList(50);

var accessLevel = 0;

var drawing = false;

function loadData()
{
 loadMessages();
 loadRooms();
}

function loadRooms()
{
 window.document.getElementById('rooms').src='chat.pl?f=rlist&rid=' + currentRoomId + '&sid=' + sid;
 roomTimeout = setTimeout("loadRooms()", 60000);
}

function loadMessages()
{
 window.document.getElementById('msgdata').src='chat.pl?f=mlist&mid=' + lastMsgId + '&rid=' + currentRoomId + '&sid=' + sid;
 msgTimeout = setTimeout("loadMessages()", 5000);
}

function clearMessages()
{
 lastMsgId = 0;
 messages.Clear();
}

function reloadMessages()
{
 cancelMessages();
 clearMessages();
 drawMessages(true);
}

function reloadRooms()
{
 cancelRooms();
 loadRooms();
}

function setRoomColor(color)
{
 var body;
 if (color != '') {
    currentRoomColor = color;
    body = window.frames[2].document.getElementById("idbody");
    if (body != null) body.bgColor = color;
 }
}

function unregister()
{
 sid = '';
 window.document.getElementById('login').src='chat.pl?f=madd';
}

function authorize(nick, pwd, ran, enc)
{
 accessLevel = 0;
 window.frames[3].location = 'chat.pl?f=login&u_nick=' + nick + '&u_pwd=' + pwd + '&u_ran=' + ran + '&q=' + enc;
}

function cancelMessages()
{
 clearTimeout(msgTimeout);
}

function cancelRooms()
{
 clearTimeout(roomTimeout);
}

/*************************************************/
function CircularList(capacity)
{
 this._capacity = capacity;
 this._tail = -1;
 this._current = 0;
 this._length = 0;
 this._full = false;
 this._data = new Array(capacity);
 this.Head = listHead;
 this.Tail = listTail;
 this.Next = listNext;
 this.Prev = listPrev;
 this.Put = listPut;
 this.Clear = listClear;
 this.Search = listSearch;
}

function listClear()
{
 this._tail = -1;
 this._current = 0;
 this._length = 0;
 this._full = false;
}

function listPut(msg)
{
 this._tail = (this._tail + 1) % this._capacity;
 if (this._length < this._capacity)
    this._length++;
 else
    this._full = true;
 this._data[this._tail] = msg;
}

function listHead()
{
 var idx;

 if (this._length == 0) return null;
 if (! this._full)
    this._current = 0;
 else
    this._current = (this._tail + 1) % this._capacity;
 return this._data[this._current];
}

function listTail()
{
 if (this._length == 0) return null;
 this._current = this._tail;
 return this._data[this._current];
}

function listNext()
{
 if (this._current == this._tail) return null;
 this._current = (this._current + 1) % this._capacity;
 return this._data[this._current];
}

function listPrev()
{
 var headpos;
 if (! this._full)
    headpos = 0;
 else
    headpos = (this._tail + 1) % this._capacity;
 if (this._current == headpos) return null;
 if (--this._current < 0) this._current = this._capacity - 1;
 return this._data[this._current];
}

function listSearch(id)
{
 var current = this._current;
 var item;

 for (item = this.Head(); item != null; item = this.Next()) {
     if (item.Id == id) break;
 }

 this._current = current;
 return item;
}

/*************************************************/
function Visitor(id, nick, gender, access, ignored, status)
{
 this.Id = id;
 this.Nick = nick;
 this.Gender = gender;
 this.Access = access;
 this.Ignored = ignored;
 this.Status = status;
}

/*************************************************/
function Room(id, title, owned, flags)
{
 this._lst = 0;
 this.Id = id;
 this.Title = title;
 this.Owned = owned;
 this.Flags = flags;
 this.Visitors = new Array();

 this.IsPrivate = isRoomPrivate;
 this.KnownVisitors = knownVisitors;
 this.AddVisitor = RoomAddVisitor;
 this.NumVisitors = RoomNumVisitors;
}

function isRoomPrivate() { return this.Flags & 0x01; }
function knownVisitors() { return this.Flags & 0x02; }

function RoomAddVisitor(visitor)
{
 this.Visitors[this._lst++] = visitor;
}

function RoomNumVisitors()
{
 return this.Visitors.length;
}

/*************************************************/
function Message(id, uid, nick, nickColor, textColor, text, flags)
{
 this.Id = id;
 this.Uid = uid;
 this.Nick = nick;
 this.NickColor = nickColor;
 this.TextColor = textColor;
 this.Text = text;
 this.Flags = flags;

 this.IsPrivate = isMessagePrivate;
 this.IsPrivateSent = isMessagePrivateSent;
 this.IsPersonal = isMessagePersonal;
 this.HasMenu =  hasMessageMenu;
}

function isMessagePrivateSent() { return this.Flags & 0x08; }
function isMessagePrivate() { return this.Flags & 0x04; }
function isMessagePersonal() { return this.Flags & 0x02; }
function hasMessageMenu()    { return !(this.Flags & 0x01); }

/*************************************************/
function drawMenu()
{
 var menu = window.frames[0].document;
 var dsp1 = (accessLevel > 0  ? 'block' : 'none');
 var dsp2 = (accessLevel >= 6 ? 'block' : 'none');

 menu.getElementById('settings').style.display = dsp1;
 menu.getElementById('mail').style.display = dsp1;
 menu.getElementById('newroom').style.display = dsp1;
 menu.getElementById('search').style.display = dsp1;
 menu.getElementById('exit').style.display = dsp1;

 menu.getElementById('adm').style.display = dsp2;
}

function drawRooms()
{
 clearTimeout(roomTimeout);

 var room;
 var gender, color, ignimg, ignalt, ignact, vid, vnick, numvis;
 var hasPrivats = false;
 with (window.frames[1].document) {
   write('<html><head><link href="chat.css" rel="stylesheet" type="text/css"></head>');
   write('<BODY leftmargin=0 rightmargin=0 topmargin=0 marginheight=0 marginwidth=0 class=b1>');
   write('<table style="width:183;height:100%;" border=0 cellspacing=0 cellpadding=0 bgcolor="#9dc189">');
   write('<tr height=1>');
   write('<td width=9 height=1 background="img/dop_up_fon.gif"><img src="img/dop_up_fon.gif" width=9 height=20></td>');
   write('<td width=158 height=1 valign=top>');
   write('<table width=158 border=0 cellspacing=0 cellpadding=0>');
   write('<tr>');
   write('<td background="img/dop_up_fon.gif" width=11 align=right><img src="img/dop_up_l.gif" width=11 height=20></td>');
   write('<td class=header3 background="img/dop_up_cfon.gif" valign=bottom align=center>..:КОМНАТЫ :..</td>');
   write('<td background="img/dop_up_fon.gif" width=11><img src="img/dop_up_r.gif" width=11 height=20></td>');
   write('</tr>');
   write('</table>');
   write('</td>');
   write('<td background="img/dop_up_fon.gif" width=16><img src="img/dop_up_fon.gif" width=16 height=20></td>');
   write('</tr>');
   write('<tr><td background="img/p.gif" colspan=3 style="width:183;height:100%;" valign=top>');

   write('<table width=183 border=0 cellspacing=0 cellpadding=0>');
   for (var i=0; i < rooms.length; i++) {
       if (rooms[i].IsPrivate()) {
           hasPrivats = true; continue;
       }
       write('<tr bgcolor="#9dc189">');
       write('<td width=30 align=right><img src="img/' + ((rooms[i].Id == currentRoomId)? 'room.gif' : 'room-c.gif') + '" border=0></td>');
       write('<td class="header1" valign="bottom" height="1">');
       if (rooms[i].Owned)
          write('&nbsp;<a href="javascript:parent.roominfo(' + rooms[i].Id +')" class=ip>i</a>&nbsp;');
       else
          write('&nbsp;&nbsp;&nbsp;');

       numvis = rooms[i].KnownVisitors() ? (' (' + rooms[i].NumVisitors() + ')') : '';
       if (rooms[i].Id == currentRoomId)
          write('<span class="header1">' + rooms[i].Title + numvis + '</span></td>');
       else
          write('<a class="header1" href="chat.pl?f=renter&rid=' + rooms[i].Id + '&sid=' + sid + '">' + rooms[i].Title + numvis + '</a></td>');
       write('</tr>');
       if (rooms[i].NumVisitors() > 0) {
          write('<tr bgcolor="#9dc189">');
          write('<td width=1><img src="img/p.gif" width=1 height=1></td>');
		  write('<td bgcolor="#000000" valign=top>');
          write('<table width="100%" border=0 cellspacing=0 cellpadding=0>');
          for (var j = 0; j < rooms[i].NumVisitors(); j++) {
              write('<tr bgcolor="#9dc189" style="height:16px; line-height:12px;">');
              vid = rooms[i].Visitors[j].Id;
              vnick = rooms[i].Visitors[j].Nick;
              if (rooms[i].Visitors[j].Ignored == 1) {
                 ignimg = 'ig.jpg'; ignalt = 'Снять игнор'; ignact = 0;
              }
              else {
                 ignimg = 'nig.gif'; ignalt = 'Поставить игнор'; ignact = 1;
              }
              gender = rooms[i].Visitors[j].Gender;
              color = (gender == 0 ? '#009900' : gender == 1 ? '#cb3a6d' : '#ffffff');
              if (accessLevel > 0) {
                 write('<td width=38 style="font-family: Arial; font-size: 12px" NOWRAP>');
                 write('<a href="javascript:parent.ignore(' + vid + ',' + ignact + ')" class=ip>');
                 write('<img src="img/' + ignimg + '" align=absbottom width=16 height=16 alt="' + ignalt + '" border=0>');
                 write('</a>');
                 write('&nbsp;<a href="javascript:parent.pr(' + vid + ')" class=ip>p</a>&nbsp;');
                 write('<a href="javascript:parent.personal(' + vid + ', \'' + vnick + '\');"><img src="img/to.gif" width=8 height=8 align=middle border=0 alt="Личное сообщение"></a>');
                 write('</td>');
              }
              write('<td width=6 align=center>');
              if (rooms[i].Visitors[j].Access > 1)
                 write('<font color=red><b>!</b></font>');
              else
                 write('&nbsp;');
              write('</td>');
              write('<td width=108><A class="nick2" href="javascript:parent.userinfo(' + vid + ')" ><font color="' + color + '">' + rooms[i].Visitors[j].Nick + '</font></A></td>');
              write('<td class=ustat valign=top nowrap><img src="img/p.gif" border=0 width=3>' + rooms[i].Visitors[j].Status + '</td>');
              write('</tr>');
          }
          write('</table></td></tr>');
       }
   }

   if (hasPrivats) {
       write('<tr bgcolor="#9dc189">');
       write('<td width=1><img src="img/p.gif" width=1 height=1></td>');
       write('<td class=header2 align=center>Мои приваты</td>');
       write('</tr>');

       for (var i=0; i < rooms.length; i++) {
           if (! rooms[i].IsPrivate()) continue;
           write('<tr bgcolor="#9dc189">');
           write('<td width=1><img src="img/p.gif" width=1 height=1></td>');
           write('<td class="header1" bgcolor="#9dc189"><a href="javascript:parent.delroom(' + rooms[i].Id + ')" class=ip><img src="img/cross.gif" width=16 height=16 align=absbottom alt="Уничтожить" border=0></a>' + rooms[i].Title + '</td>');
           write('</tr>');
       }
   }
   write('</table>');
   write('</td></tr></table></body>');
 }

 roomTimeout = setTimeout("loadRooms()", 60000);
}

function drawMessages(reload)
{
 drawing = true;

 var current   = (scrolling == 0 ? messages.Tail() : messages.Head());
 var roomColor = (currentRoomColor == '' ? 'E0E0E0' : currentRoomColor);

 // Ни один браузер, кроме IE, не позволяет создать документ с помощью комбинации open/write/close и DOM-операций. Пришлось дублировать
 // функции рисования списка сообщений (см. drawOneMessage). Бред какой-то!
 with (window.frames[2].document) {
   open();
   write('<html><head><link href="chat.css" rel="stylesheet" type="text/css"></head>');
   write('<BODY id="idbody" bgcolor="' + roomColor + '" leftmargin=0 rightmargin=0 topmargin=0 marginheight=0 marginwidth=0>');
   write('<div id=menu class=m onmouseout="parent.menuClose(event);"></div>');
   write('<table id="msgs" width="100%" border=0 cellspacing=2 cellpadding=0>');

   while (current != null) {
     write('<tr>');
     write('<td width=16>');
     if (current.IsPrivate())
        write('<span class=exclr>!</span>');
     else if (current.IsPrivateSent())
        write('<span class=exclb>!</span>');
     else if (current.IsPersonal())
        write('<span class=exclg>!</span>');
     else
         write('&nbsp;');
     write('&nbsp;');
     if (accessLevel > 0 && current.HasMenu())
        write('<a href="javascript:parent.personal(' + current.Uid + ', \'' + current.Nick + '\');"><img src="img/to.gif" width=8 height=8 align=middle border=0 alt="Личное сообщение"></a>');
     write('</td>');
     write('<td class=text>');
     if (accessLevel > 0 && current.HasMenu())
        write('<span class="nick"><a href="#" style="color:' + current.NickColor + '" id=m' + current.Id + ' onClick="return parent.menu(' + current.Id + ', event);">' + current.Nick + ':</a></span>');
     else
        write('<span class="nick"><font color="' + current.NickColor + '">' + current.Nick + ':</font></span>');
     write('&nbsp;<font color="' + current.TextColor + '">' + current.Text + '</font>');
     write('</td></tr>');

     current = (scrolling == 0 ? messages.Prev() : messages.Next());
   }
   write('</table>');
   write('</BODY></HTML>');
   close();
 }

 drawing = false;

 if (scrolling != 0) {
    window.frames[2].scrollTo(0, 1000);
 }
 if (reload) {
    clearTimeout(msgTimeout);
    loadMessages();
 }
 return true;
}

function mergeMessages(list, topid)
{
 for (var i = list.length - 1; i >= 0; i--)
     if (list[i].Id > topid) messages.Put(list[i]);
}

function updateMessages(list, topid)
{
 var hasPersonal = false, hasPrivate = false, doScroll = false;

 with (window.frames[2].document) {
    if (scrolling != 0 && body.clientHeight + body.scrollTop >= body.scrollHeight)
       doScroll = true;
    var table = getElementById("msgs");
    if (typeof(table) != 'object') return;

    for (var i = list.length - 1; i >= 0; i--) {
        if (list[i].Id <= topid) continue;
        if (list[i].IsPrivate()) hasPrivate = true;
        if (list[i].IsPersonal() && !hasPrivate) hasPersonal = true;
        drawOneMessage(table, list[i]);
    }

    if (hasPrivate || hasPersonal) {
       var bgsound = createElement('BGSOUND');
       if (bgsound != null) {
          bgsound.src = 'img/' + (hasPersonal ? 'personal.wav' : 'private.wav');
          bgsound.loop = 1;

          var b = getElementById("idbody");
          b.appendChild(bgsound);
       }
    }
 }
 if (doScroll)
    window.frames[2].scrollTo(0, 1000);
}

function drawOneMessage(tbl, msg)
{
 with (window.frames[2].document) {
    var pos = (scrolling == 0 ? 0 : tbl.rows.length);
    var row = tbl.insertRow(pos);
    var cell = row.insertCell(0);
    cell.width = 16;

    var content = '!';
    var span = createElement('SPAN');
    if (msg.IsPrivate())
       span.className = 'exclr';
    else if (msg.IsPrivateSent())
       span.className = 'exclb';
    else if (msg.IsPersonal())
       span.className = 'exclg';
    else
       content = '&nbsp;';
    content += '&nbsp;';

    span.innerHTML = content;
    cell.appendChild(span);

    if (accessLevel > 0 && msg.HasMenu()) {
       var img = createElement("IMG");
       img.src = "img/to.gif";
       img.width = 8;
       img.height = 8;
       img.align = 'middle';
       img.border = 0;
       img.alt = 'Личное сообщение';

       var a = createElement("A");
       a.href = "javascript:parent.personal(" + msg.Uid + ", '" + msg.Nick + "');"

       a.appendChild(img);
       cell.appendChild(a);
    }

    cell = row.insertCell(1);
    cell.className = 'text';
    var it = createElement("I");
    cell.appendChild(it);
    span = createElement('SPAN');
    span.className = 'nick';
    it.appendChild(span);
    var nick = createTextNode(msg.Nick + ':');
    if (accessLevel > 0 && msg.HasMenu())
       span.innerHTML = '<a href="#" style="color:' + msg.NickColor + '"  onClick="return parent.menu(' + msg.Id + ', event);">' + msg.Nick + ':</a>';
    else {
       var font = createElement('FONT');
       font.color = msg.NickColor;
       font.appendChild(nick);
       span.appendChild(font);
    }
    var msgtext = createElement('FONT');
    msgtext.color = msg.TextColor;
    msgtext.innerHTML = '&nbsp;' + msg.Text;
    cell.appendChild(msgtext);

    if (tbl.rows.length > 50)
       tbl.deleteRow(scrolling == 0 ? tbl.rows.length - 1  : 0)
 }
}

function whatsnew(newMessages, newAccess, newScrolling, newSound, newRoomId, newLastMsgId)
{
 if (drawing) return;

 var redraw = false, isRegistered = true, menuChanged = false, topid = lastMsgId;
 if (accessLevel != newAccess) {
    clearMessages();
    topid = 0;
    redraw = true;
    menuChanged = true;
    if (newAccess == 0) isRegistered = false;
 }
 else if (newRoomId != currentRoomId) {
    clearMessages();
    topid = 0;
    redraw = true;
 }
 else if (scrolling != newScrolling) {
    redraw = true;
 }

 mergeMessages(newMessages, topid);

 accessLevel = newAccess;
 currentRoomId = newRoomId;
 scrolling = newScrolling;
 if (newLastMsgId > 0) lastMsgId = newLastMsgId;
 if (redraw)
    drawMessages(false);
 else if (newMessages.length > 0)
    updateMessages(newMessages, topid);

 if (!isRegistered) unregister();
 if (menuChanged) drawMenu();
}

function smile(idx)
{
 var input;
 eval ("input = window.frames[3].document.forms[0].msg;");
 if (typeof(input) != 'object') return;

 var sml;
 if (idx > 0 && idx <= smiles.length) {
    input.value = input.value + smiles[idx - 1];
    input.focus();
 }
}

function userinfo(uid)
{
 open('chat.pl?f=uinfo&u_id=' + uid + '&sid=' + sid, "_blank", "width=670,height=500,resizable=1,scrollbars=1");
}

function recent(uid)
{
 open('chat.pl?f=umess&u_id=' + uid + '&sid=' + sid, "_blank", "width=670,height=500,resizable=1,scrollbars=1");
}

function personal(uid, nick)
{
 var to, excl, cb_to, cb_excl, hidden, msg;
 eval ("msg=window.frames[3].document.forms[0].msg; cb_to=window.frames[3].document.forms[0].personal; cb_excl=window.frames[3].document.forms[0].excl; to=window.frames[3].document.getElementById('to'); excl=window.frames[3].document.getElementById('excl'); hidden=window.frames[3].document.forms[0].tid;");
 if (typeof(cb_to) != 'object' || typeof(hidden) != 'object' || to == null) return;

 cb_to.checked = true; cb_to.disabled = false;
 hidden.value = uid;
 to.innerText = nick;
 if (excl != null) excl.style.display='inline';
 if (typeof(cb_excl) == 'object') cb_excl.checked = false;
 if (typeof(msg) == 'object') {
   msg.focus();
   msg.value = '[' + nick + ']: ' + msg.value;
 }
}

function settings()
{
 window.frames[2].location.href = "chat.pl?f=setf&sid=" + sid;
}

function roomcreate()
{
 window.frames[1].location.href = "chat.pl?f=rcreatef&sid=" + sid;
}

function roominfo(rid)
{
 open('chat.pl?f=redit&rid=' + rid + '&sid=' + sid, "_blank", "width=330,height=290,scrollbars=0");
}

function search()
{
 open('chat.pl?f=srchf&sid=' + sid, "_blank", "width=280,height=120,resizable=1,scrollbars=1");
}

function mail()
{
 open('chat.pl?f=mxbox&sid=' + sid, "_blank", "width=640,height=480,resizable=1,scrollbars=1");
}

function pr(uid)
{
 open('chat.pl?f=popen&uid=' + uid + '&sid=' + sid, "_blank", "width=640,height=480,resizable=1,scrollbars=1");
}

function block(uid)
{
 open('chat.pl?f=modblock&UIDtime=60&u_id=' + uid + '&sid=' + sid, "_blank", "width=670,height=500,resizable=1,scrollbars=1");
}

function moder(uid)
{
 open('chat.pl?f=modform&u_id=' + uid + '&sid=' + sid, "_blank", "width=670,height=500,resizable=1,scrollbars=1");
}

function modprop(uid)
{
 window.frames[2].location.href = 'chat.pl?f=modprop&u_id=' + uid + '&sid=' + sid;
}

function adm()
{
 window.frames[2].location.href = "chat.pl?f=modlist&sid=" + sid;
}

function ignore(uid, ignact)
{
 cancelRooms();
 window.frames[1].location.href = 'chat.pl?f=ign&uid=' + uid + '&sid=' + sid + '&op=' + ignact;
}

function delroom(rid)
{
 cancelRooms();
 window.frames[1].location.href = 'chat.pl?f=rdel&rid=' + rid + '&sid=' + sid;
}

function logout()
{
 window.frames[0].location.href = 'chat.pl?f=logout&sid=' + sid;
}

function menu(mid, event)
{
 var msg = parent.messages.Search(mid);
 if (msg == null) {
    event.returnValue=false;
    return false;
 }
 var el, x, y, id;

 with (window.frames[2]) {
    el = document.getElementById("menu");
    var o = event.srcElement;
    if (typeof(o) == 'undefined') o = event.target;
    if (o.tagName != "A") return true;
    el.innerHTML = '<SPAN class=mh>' + msg.Nick + '</SPAN>' +
                   '<A class=mi HREF="javascript:parent.pr(' + msg.Uid + '); parent.menuHide()">Открыть приват</A>' +
                   '<A class=mi HREF="javascript:parent.userinfo(' + msg.Uid + '); parent.menuHide()">Инфо</A>' +
                   '<A class=mi HREF="javascript:parent.recent(' + msg.Uid + '); parent.menuHide()">Из недавнего</A>' +
                   '<A class=mi HREF="javascript:parent.ignore(' + msg.Uid + ', 1); parent.menuHide()">Игнор</A>';
    if (parent.accessLevel > 1)
       el.innerHTML +=
                   '<SPAN class=mi>---------</SPAN>' +
                   '<A class=mi HREF="javascript:parent.block(' + msg.Uid + '); parent.menuHide()">блокировать на 1 мин</A>' +
                   '<A class=mi HREF="javascript:parent.moder(' + msg.Uid + '); parent.menuHide()">Модерация</A>';
    x = event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft - 3;
    y = event.clientY;
    y -= 2;
    if (y + el.offsetHeight > document.body.clientHeight) { y=document.body.clientHeight-el.offsetHeight-2 }
    y += document.body.scrollTop;
    el.style.left = x + "px";
    el.style.top  = y + "px";
    el.style.visibility = "visible";
    event.returnValue=false;
 }

 return false;
}

function menuHide() {
  window.frames[2].document.getElementById("menu").style.visibility = "hidden";
}

function menuClose(event) {
  if (event != null) {
     var o = event.toElement;
     if (typeof(o) == 'undefined') o = event.relatedTarget;
     if (o != null) {
        var cls = o.className;
        if (cls=='m' || cls=='mi' || cls=='mh') return true;
     }
  }
  menuHide();
  return true;
}

