context: /*
  	Copyright 2010 MCSharp Team Licensed under the
  	Educational Community License, Version 2.0 (the "License"); you may
  	not use this file except in compliance with the License. You may
  	obtain a copy of the License at
  	
  	http://www.osedu.org/licenses/ECL-2.0
  	
  	Unless required by applicable law or agreed to in writing,
  	software distributed under the License is distributed on an "AS IS"
  	BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  	or implied. See the License for the specific language governing
  	permissions and limitations under the License.
  */
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Text;
  using System.Windows.Forms;
  using System.Threading;
  using System.Text.RegularExpressions;
  using System.Net;
  using System.IO;
  using System.IO.Compression;
  
  using Overv;
  
  namespace Overv.Gui
  {
      public partial class Window : Form
      {
          Regex regex = new Regex(@"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\." +
                                  "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$");
          // for cross thread use
          delegate void StringCallback(string s);
          delegate void PlayerListCallback(List<Player> players);
          delegate void VoidDelegate();
  
          internal static Server s;
          
          bool shuttingDown = false;
          public Window()
          {
              InitializeComponent();
          }
  
          private void Window_Load(object sender, EventArgs e)
          {
              this.Text = "<server name here>";
              
              s = new Server();
              s.OnLog += WriteLine;
              s.OnCTFLog += WriteCTFLine;
              s.HeartBeatFail += HeartBeatFail;
              s.OnURLChange += UpdateUrl;
              s.OnPlayerUpdate += UpdatePlayerBalloon;
              s.OnPlayerListChange += UpdateClientList;
              s.OnSettingsUpdate += SettingsUpdate;
              s.Start();
  
              System.Timers.Timer statsTimer = new System.Timers.Timer( 2000 );
              statsTimer.Elapsed += delegate {
                  UpdateStats();
              };
              statsTimer.Start();
  
              UpdateMaps();
          }
  
          static List<MapInfo> availableMaps = new List<MapInfo>();
  
          struct MapInfo {
              public string name;
              public string author;
              public string description;
              public string image;
  
              public MapInfo( string nname, string nauthor, string ndescription, string nimage ) {
                  name = nname;
                  author = nauthor;
                  description = ndescription;
                  image = nimage;
              }
          }
  
          void UpdateMaps() {
              try {
                  WebClient wc = new WebClient();
                  wc.DownloadFile( "http://mcderp.x10.mx/downloads/availablemaps.txt", "text/maps.txt" );
                  foreach ( string line in File.ReadAllLines( "text/maps.txt" ) ) {
                      availableMaps.Add( new MapInfo( line.Split( ':' )[0].Trim(), line.Split( ':' )[1].Trim(), line.Split( ':' )[2].Trim(), line.Split( ':' )[3].Trim() ) );
                  }
                  wc.Dispose();
              } catch(WebException we) {
                  MessageBox.Show( "Unable to download maplist! Details: " + we.ToString() );
              }
  
              foreach ( MapInfo mi in availableMaps ) {
                  liOnlineMaps.Items.Add( mi.name );
              }
          }
  
          void UpdateStats() {
              if ( this.InvokeRequired ) {
                  VoidDelegate d = new VoidDelegate( UpdateStats );
                  this.Invoke( d );
              } else {
                  try {
                      lbCurrentLevel.Text = "Currently playing on: " + CTF.currLevel.name;
                      lbRedScore.Text = "Score: " + CTF.redTeam.points;
                      lbBlueScore.Text = "Score: " + CTF.blueTeam.points;
                      lbRedWins.Text = "Wins: " + CTF.redWins;
                      lbBlueWins.Text = "Wins: " + CTF.blueWins;
                      if ( CTF.redTeam.flagIsHome ) {
                          lbRedFlagStatus.Text = "Flag: is home.";
                      } else if ( CTF.redTeam.hasFlag != null ) {
                          lbRedFlagStatus.Text = "Flag: " + CTF.redTeam.hasFlag.name + " has it!";
                      } else {
                          lbRedFlagStatus.Text = "Flag: dropped.";
                      }
                      if ( CTF.blueTeam.flagIsHome ) {
                          lbBlueFlagStatus.Text = "Flag: is home.";
                      } else if ( CTF.blueTeam.hasFlag != null ) {
                          lbBlueFlagStatus.Text = "Flag: " + CTF.blueTeam.hasFlag.name + " has it!";
                      } else {
                          lbBlueFlagStatus.Text = "Flag: dropped.";
                      }
                      liRedPlayers.Items.Clear();
                      CTF.redTeam.players.ForEach( delegate( Player p ) {
                          liRedPlayers.Items.Add( p.name );
                      } );
                      liBluePlayers.Items.Clear();
                      CTF.blueTeam.players.ForEach( delegate( Player p ) {
                          liBluePlayers.Items.Add( p.name );
                      } );
                  } catch { 
                      // ctf is probably disabled.                 
                  }
              }
          }
  
          void SettingsUpdate() {
              if ( shuttingDown ) return;
              if ( txtServerLogs.InvokeRequired ) {
                  VoidDelegate d = new VoidDelegate( SettingsUpdate );
                  this.Invoke( d );
              } else {
                  this.Text = "Capture The Flag: " + Server.name;
              }
          }
  
          void HeartBeatFail()
          {
              WriteLine("Recent Heartbeat Failed");
          }
  
          delegate void LogDelegate(string message);
  
          /// <summary>
          /// Does the same as Console.Write() only in the form
          /// </summary>
          /// <param name="s">The string to write</param>
          public void Write(string s)
          {
              if (shuttingDown) return;
              if (txtServerLogs.InvokeRequired)
              {
                  LogDelegate d = new LogDelegate(Write);
                  this.Invoke(d, new object[] { s });
              }
              else
              {
                  txtServerLogs.AppendText(s);
              }
          }
          /// <summary>
          /// Does the same as Console.WriteLine() only in the form
          /// </summary>
          /// <param name="s">The line to write</param>
          public void WriteLine(string s)
          {
              if (shuttingDown) return;
              if (this.InvokeRequired)
              {
                  LogDelegate d = new LogDelegate(WriteLine);
                  this.Invoke(d, new object[] { s });
              }
              else
              {
                  txtServerLogs.AppendText(s + "\r\n");
              }
              
          }
  
          /// <summary>
          /// CTF LOGZZZ
          /// </summary>
          /// <param name="s"></param>
          public void WriteCTFLine( string s ) {
              if ( shuttingDown ) return;
              if ( this.InvokeRequired ) {
                  LogDelegate d = new LogDelegate( WriteCTFLine );
  
gt:                 this.Invoke( d, new object[] { s } );