// import QxLoader

// [PyWebTop ChatWidget]
qx.Class.define("PwtChat",
{
   extend : qx.ui.container.Composite,

   construct: function(chatuid)
   {
      // [Superclass]
      this.base(arguments);
      this.chatuid = chatuid;
      if(typeof chatuid != 'string') {
         this.chatuid = chatuid.toString();
      }

      this.setLayout(new qx.ui.layout.VBox(10));

      // Set latest message to null
      this.latestsender = null;
      this.username = null;

      // TopBox
      var outputarea = new qx.ui.container.Composite(new qx.ui.layout.HBox(10));
      this.add(outputarea, {flex:1});
      this.outputarea = outputarea;

      // ChatArea (left or unique)
      var chatarea = new qx.ui.embed.Html();
      chatarea.setOverflow("auto", "auto");
      chatarea.setBackgroundColor("white");
      chatarea.setDecorator("main");
      this.outputarea.add(chatarea, {flex:1});
      this.chatarea = chatarea;
      // Enable right click native menu on this area
      // XXX Temporaneo, poi dovrai reimplementare il copia e incolla
      // dal tuo menu'
      this.chatarea.setNativeContextMenu(true);


      // ListArea (right or not showed)
      // XXX: We are sure to use an embed.html widget?
      //var listarea = new qx.ui.embed.Html();
      // TODO: Aggiungi l'evento losefocus che elimina la seleziona dalla lista?
      var listarea = new qx.ui.virtual.form.List();
      //listarea.setOverflow("auto", "auto");
      listarea.setBackgroundColor("white");
      // XXX: Vogliamo una dimensione fissa in questo modo?
      listarea.setWidth(120);
      //listarea.setRowHeight(15); // XXX: siamo al limite, i caratteri non cambiano.
      //listarea.setDecorator("main");
      this.listarea = listarea;
      this.list = new qx.data.Array([]);
      this.listcontroller = new qx.ui.virtual.form.ListController(this.list, this.listarea);



      // BottomBox
      var inputarea = new qx.ui.container.Composite(new qx.ui.layout.HBox(10));
      this.add(inputarea, {flex:0});
      this.inputarea = inputarea;

      // ChatInput (left side)
      //var chatinput = new qx.ui.form.TextField();
      var chatinput = new qx.ui.form.TextArea();
      chatinput.setAllowGrowY(false);
      chatinput.setMaxLength(1024);
      this.inputarea.add(chatinput, {flex:1});
      this.chatinput = chatinput;
      // Enable right click native menu on this area
      // XXX Temporaneo, poi dovrai reimplementare il copia e incolla
      // dal tuo menu'
      this.chatinput.setNativeContextMenu(true);



      // ChatButton (right side)
      var chatbutton = new qx.ui.form.Button("Invia");
      //chatbutton.setHeight(15);
      chatbutton.setHeight(65);
      chatbutton.setAllowGrowX(false);
      chatbutton.setAllowGrowY(false);
      this.inputarea.add(chatbutton);
      this.chatbutton = chatbutton;
      // Disabled by default
      this.chatbutton.setEnabled(false);


      // Manage Events
      // XXX Bisogna mandare lo scroll al bottom anche al resize!
      //this.chatarea.addListener("click", this.chatClicked, this);
      this.chatarea.addListener("changeHtml", this.chatChanged, this);
      this.chatinput.addListener("input", this.chatInputEvent, this);
      this.chatbutton.addListener("execute", this.buttonClicked, this);
      this.addListener("keyinput", this.keyInput, this);
      this.addListener("keypress", this.keyPress, this);
      this.listarea.addListener("dblclick", this.doubleClick, this);

   },

   members:
   {

      athena: function()
      {  
         return Nevow.Athena.Widget._athenaWidgets[1];
      },


      showListBox: function()
      {
         // Add an UserList bot on the right side of the TopBox
         this.outputarea.add(this.listarea, {flex:0});
         this.listarea.addListener("contextmenu", this.listContextMenu, this);
         // This can be fetched only when we are really "ready"
         this.getUserList();
      },

      listContextMenu: function()
      {
         // TODO: Apri il menu solo se qualcosa e' selezionato
         // XXX: BUG: la prima volta il menu' su apre sotto il widget!
         uselect = this.listcontroller.getSelection();
         if(uselect.length > 0) {
            menu = new qx.ui.menu.Menu();
            this.listarea.setContextMenu(menu);
            var button = new qx.ui.menu.Button('Private msg');
            button.addListener("execute", this.openPrivate, this);
            menu.add(button);
            menu.open();
         }
      },

      openPrivate: function()
      {
         uselect = this.listcontroller.getSelection();
         if(uselect.length > 0) {
             var target = uselect.toString();
             qx.core.Init.getApplication().openPrivate(target);
         }
      },

      doubleClick: function()
      {
         alert('double click');
      },
      
      getUserList: function()
      {
         try {
            this.athena().getUserList();
         } catch(err) {
            qx.event.Timer.once(this.getUserList, this, 1000);
         }
      },

      /*
      chatClicked: function() 
      {
         alert(this.chatarea.getFocusElement().getTextSelection());
      },
      */

      addChatLine: function(sender, line)
      {
         var html = qx.xml.String.escape(line);
         var from = qx.xml.String.escape(sender);

         // Prendi il contenuto della root DOM contenuta nel widget
         var el = this.chatarea.getContentElement();
         var elem = el.getDomElement();
         var nel = qx.dom.Hierarchy.getChildElements(elem);

         // Se sono troppe, elimina il primo child
         if(nel.length>1000) {
            var toberemoved=qx.dom.Hierarchy.getFirstDescendant(elem);
            qx.dom.Element.removeChild(toberemoved, elem);
            qx.ui.core.queue.Manager.flush();
         }

         //var oldhtml = this.chatarea.getHtml();
         //if(oldhtml===null) { oldhtml='' }
         //this.chatarea.setHtml(oldhtml+this.text2chat(from, html));
         qx.dom.Element.insertEnd(this.text2chat(from, html), elem);

         // Flusha la coda eventi per essere sicuri che i passaggi successivi
         // vengano fatti sul widget gia' aggiornato come contenuto.
         qx.ui.core.queue.Manager.flush();
         
         
         // Scrolla al bottom
         elem.scrollTop = elem.scrollHeight;
      },

      chatInputEvent: function(evt)
      {
         //var value = this.chatinput.getValue();
         var value = evt.getData();
         this.chatbutton.setEnabled(value.length <= 1024 && value.length > 0);
      },

      chatChanged: function(change)
      {
         // TODO: Limitiamo qui il numero massimo di righe?
         // XXX Sembra inutile beccare sto evento, lo scroll qui non va perche'
         // l'evento e' dispatchato troppo presto, quindi ho spostato la logica nella 
         // funzione addChatLine direttamente.
         var elem = this.chatarea.getContentElement().getDomElement();
      },


      buttonClicked: function()
      {
         if(this.username===null) { 
            this.athena().getUsername().addCallback(
               function(ret, cl) {
                  cl.username = ret;
                  cl.chatSend();
            }, this); 
         } else {
            this.chatSend();
         }
      },

      chatReceived: function(msg, who)
      {
         var sender = '<'+who+'> ';
         if(who==this.lastsender) { var sender = '... ' }
         this.lastsender = who;
         this.addChatLine(sender, msg);
      },

      updateListArea: function(ulist)
      {
         this.list = new qx.data.Array(ulist);
         this.listcontroller = new qx.ui.virtual.form.ListController(this.list, this.listarea);
         //alert(ulist);
      },

      chatSend: function()
      {
         var data = this.chatinput.getValue();
         if(data!==null) {
            this.chatReceived(data, this.username);
            this.athena().sendChat(data, this.chatuid);
         }
         this.chatinput.resetValue();
         //this.chatinput.setValue(null); 
         this.chatbutton.setEnabled(false);
      },

      keyInput: function(evt)
      {
         if( this.chatinput != qx.ui.core.FocusHandler.getInstance().getFocusedWidget()) {
            val = this.chatinput.getValue();
            if(val!=null) {
               nval = val+evt.getChar();
            } else {
               nval = val;
            }
            this.chatinput.setValue(nval);
            this.chatinput.focus();
         }
      },

      keyPress: function(evt)
      {
         if(evt.getKeyIdentifier()=="Enter") {
            //alert(this.chatinput.getValue());
            evt.preventDefault();
            if(this.chatinput.getValue()!==null) {
              this.chatbutton.fireEvent("execute");
            }
         } 

      },

      text2chat: function(from, html)
      {
         var ctime = new Date();
         var h = ctime.getHours();
         var m = ctime.getMinutes();
         var s = ctime.getSeconds();
         if(h<10) { h='0'+h; }
         if(m<10) { m='0'+m; }
         if(s<10) { s='0'+s; } 
         data = h+":"+m+":"+s;
         var color='green';
         if(this.username==this.lastsender) { 
            var color='red'; 
         } else if(this.lastsender=='Server Skylive') {
            var color='gray';
         }
         var newhtml = '<span style=\'color:gray;\'><b>['+data+']</b> </span><span style=\'color:'+color+';\'><b>'+from+'</b></span> '+html;

         var nel = qx.bom.Element.create('div');
         nel.innerHTML = this.autolink(newhtml);
         return nel;

      },

      autolink: function(s)
      {
         //var hlink = /\s(http|ftp|sip|https):\/\/([^ \,\;\:\!\)\(\"\'\<\>\f\n\r\t\v])+/g;
         var hlink = /(\s|\A)(((news|telnet|nttp|file|http|ftp|https|sip):\/\/\S+)|((www|ftp)\.([^ \,\;\:\!\)\(\"\'\<\>\f\n\r\t\v])+\.\S+))/g;
         //var hlink = /(\s|\A)(((news|telnet|nttp|file|http|ftp|https|sip)://\S+)|((www|ftp)\.[a-zA-Z]+\.\S+))/;
         return (s.replace (hlink, function ($0,$1,$2) {
            s = $0.substring(1,$0.length);
            // remove trailing dots, if any
            while (s.length>0 && s.charAt(s.length-1)=='.')
               s=s.substring(0,s.length-1);
            // add hlink
            //lk = s.link('#');
            //lk.onclick(alert(s+'AAA'));
            // XXX: Se l'uri non inizia con http:// o sun altro handler, non lo apre correttamente.
            lk = "<a href='#' onClick='window.open(\""+s+"\");'>"+s+"</a>";
            return " " + lk;
         }));
      }
   } // end members
});
   

// [PyWebTop Desktop]
qx.Class.define("PwtDesktop",
{
   extend : qx.ui.container.Composite,

   // [Entry point]
   construct: function()
   {
      // [Superclass]
      //this.base(new qx.ui.layout.Dock());
      this.base(arguments, new qx.ui.layout.Dock());



      // [Desktop Structure]
      this._canvas = new qx.ui.container.Composite(new qx.ui.layout.Canvas());
      this.add(this._canvas, {edge:"north", height: "100%"});


      // [Desktop Manager]
      this._wm = new qx.ui.window.Manager();
      this._desktop = new qx.ui.window.Desktop(this._wm);
      this._bg = new qx.ui.decoration.Background();
      this._bg.setBackgroundImage("http://danex.nexlab.it/ngc5128.jpg");
      this._canvas.add(this._desktop, {height: "100%", width:"100%", bottom:31, top:0});
      this._desktop.setDecorator(this._bg);


      // [TaskBar]
      this.addTaskBar();

   },  



   members:
   {
      addTaskBar: function()
      {
         /* 
         * A simple Task Bar 
         */

         this._toolbar = new qx.ui.toolbar.ToolBar();
         menu = new qx.ui.menu.Menu();
         exitbutton = new qx.ui.menu.Button("EXIT");
         menu.add(exitbutton);

         menubutton = new qx.ui.toolbar.MenuButton("Start", "/img/favicon.jpg");
         menubutton.setShowArrow(false);
         menubutton.setMenu(menu);
         this._toolbar.add(menubutton);
         this._toolbar.setWidth(window.innerWidth+1);
         this._toolbar.setHeight(30)

         this._toolbar.add(new qx.ui.toolbar.Separator());

         this.add(this._toolbar, {edge:"south"});

         exitbutton.addListener("execute", this.exitClicked, this);

      },

      athena: function()
      {  
         return Nevow.Athena.Widget._athenaWidgets[1];
      },


      exitClicked: function()
      {
         this.athena().exitTelescope('all', true);
         window.location = "/__logout__";
      },

      addWindow: function(widget, options)
      {
         return this._desktop.add(widget, options);
      },

      addWidget: function(widget, options)
      {
         return this._desktop.add(widget, options);
      }

   }

});


// [PyWebTop Application
qx.Class.define("PwtApplication",
{
   extend : qx.application.Standalone,

   members :
   {
      // [Entry point]
      main: function()
      {
         // [SuperClass]
         this.base(arguments);
         
         // Initialize Desktop
         this.desktop = new PwtDesktop();
         this.getRoot().add(this.desktop, {edge: 0});
      },

      // [Athena Bridge]
      athena: function()
      {
         return Nevow.Athena.Widget._athenaWidgets[1];
      }
   }
});



// [Real Application]
qx.Class.define("skyliveX.Application",
{
  extend : PwtApplication,

  members :
  {
    // [Entry point]
    main: function()
    {
      // [SuperClass]
      this.base(arguments);

      // XXX TODO: This is for test only!
      this.addChatWindow();
      this.userlist = ['unknown'];
      this.chat.showListBox();

      this.privates = Object();

      //this.openTelescopeList();

    },

   openTelescopeList: function()
   {
     // XXX Barra laterale, non sta roba!
      this.tlistwin = new qx.ui.window.Window();
      

      this.telescopelist = new qx.ui.virtual.form.List();
      this.telescopelist.setBackgroundColor("white");
      this.telescopelist.setWidth(120);
      this.telescopelist.setHeight(120);
      this.tlist = new qx.data.Array(['a','b']);
      this.listcontroller = new qx.ui.virtual.form.ListController(this.tlist, this.telescopelist);
      //this.tlistwin.add(this.telescopelist, {});
      //this.desktop.addWindow(this.tlistwin, {});
      this.desktop.addWindow(this.telescopelist, {});

   },

   chatReceived: function(arg1, arg2)
   {
      this.chat.chatReceived(arg1, arg2);
   },

   openPrivate: function(target)
   {
      this.privReceived(null, target);
   },

   privReceived: function(msg, sender)
   {
      // NOTE: This is for compatibility with the old SkyliveNG Protocol...
      if (sender.substring(0, 1) in {'@':1, '>':1, '!':1}) {
         sender = sender.substring(1);
      }
      if(this.privates[sender]===undefined) {
         this.privates[sender] = Object();
         this.privates[sender]['win'] = new qx.ui.window.Window("Private with "+sender);
         this.privates[sender]['win'].setLayout(new qx.ui.layout.HBox(10));
         this.privates[sender]['win'].setShowStatusbar(false);
         this.privates[sender]['win'].open();
         this.desktop.addWindow(this.privates[sender]['win']);

         this.privates[sender]['chat'] = new PwtChat(sender);
         this.privates[sender]['win'].add(this.privates[sender]['chat'], {flex:1});
         this.privates[sender]['chat'].setMinWidth(250);
         this.privates[sender]['chat'].setMinHeight(250);
         this.privates[sender]['win'].addListener("disappear", function(e) { this.privates[sender]=undefined; }, this);
         if(msg!==null) {
            qx.ui.core.queue.Manager.flush();
         }
      }

      if(msg!==null) {
         this.privates[sender]['chat'].chatReceived(msg, sender);
      }
   },

   userListReceived: function(ulist) 
   {
      this.chat.updateListArea(ulist);
   },

   addChatWindow: function()
   {
      var win = new qx.ui.window.Window("Chat Window");
      win.setLayout(new qx.ui.layout.HBox(10));
      win.setShowStatusbar(false);
      win.setStatus("Prova");
      win.open();
      this.desktop.addWindow(win, {left:0, top:0});

      var chat = new PwtChat('1');
      win.add(chat, {flex:1});
      this.chatwin = win;
      this.chat = chat;
      chat.setMinWidth(400);
      chat.setMinHeight(400);


      // XXX Temporaneo
      this.live = new qx.ui.basic.Image("http://skylive.astronomix.org/tele1/live640.jpg");
      refreshlive = new qx.event.Timer(5000);
      refreshlive.addListener('interval',function(e) {
        var ctime = new Date();
        var ts=ctime.getTime();
        
        // XXX Settango il background dovremmo evitare il flash al cambio immagine sui client lenti...
        //this._livebg = new qx.ui.decoration.Background();
        // this._livebg.setBackgroundImage("http://http://skylive.astronomix.org/tele1/live640.jpg?"+ts);
        //this.live.setDecorator(this._livebg);

        this.live.setSource("http://skylive.astronomix.org/tele1/live640.jpg?"+ts); 
         // XXX This way we solve?
         //qx.ui.core.queue.Manager.flush();

      }, this);
      refreshlive.start();

      var right = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
      right.add(this.live);

      var lfbutton = new qx.ui.form.Button("Ultima Foto");
      //chatbutton.setHeight(15);
      //chatbutton.setHeight(65);
      lfbutton.setAllowGrowX(false);
      lfbutton.setAllowGrowY(false);
      right.add(lfbutton);

      lfbutton.addListener("execute", 
         function() {
            var prewin  = new qx.ui.window.Window("Preview");
            prewin.setLayout(new qx.ui.layout.VBox(10));
            prewin.setShowStatusbar(false);
            prewin.open();

            pre = new qx.ui.basic.Image("http://skylive.astronomix.org/tele1/foto.jpg");
            prewin.add(pre);
            var dbutton = new qx.ui.form.Button("Scarica FIT");
            dbutton.addListener("execute", function()
            {
               window.open("http://skylive.astronomix.org/tele1/SkyFrame.Sky");
            }
            , this);
            prewin.add(dbutton);
         }
      , this);

      win.add(right, {flex:0});

   }
  }
});

