/* -*- Mode: C; tab-width: 4 -*-
 *
 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
 *
 * Licensed under the Apache 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.apache.org/licenses/LICENSE-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.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Data;
using System.Text;
using Bonjour;
namespace SimpleChat.NET
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	/// 
	public class SimpleChat : System.Windows.Forms.Form
	{
		private System.Windows.Forms.ComboBox   comboBox1;
		private System.Windows.Forms.TextBox    textBox2;
		private System.Windows.Forms.Button     button1;
		private System.Windows.Forms.Label      label1;
        private Bonjour.DNSSDEventManager       m_eventManager = null;
        private Bonjour.DNSSDService            m_service = null;
        private Bonjour.DNSSDService            m_registrar = null;
        private Bonjour.DNSSDService            m_browser = null;
        private Bonjour.DNSSDService            m_resolver = null;
		private String					        m_name;
        private Socket                          m_socket = null;
        private const int                       BUFFER_SIZE = 1024;
        public byte[]                           m_buffer = new byte[BUFFER_SIZE];
        public bool                             m_complete = false;
        public StringBuilder                    m_sb = new StringBuilder();
        delegate void                           ReadMessageCallback(String data);
        ReadMessageCallback                     m_readMessageCallback;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.RichTextBox richTextBox1;
		// ServiceRegistered
		//
		// Called by DNSServices core as a result of Register()
		// call
		//
        public void
        ServiceRegistered
                    (
                    DNSSDService service,
                    DNSSDFlags flags,
                    String name,
                    String regType,
                    String domain
                    )
        {
            m_name = name;
			//
			// Try to start browsing for other instances of this service
			//
            try
            {
                m_browser = m_service.Browse(0, 0, "_p2pchat._udp", null, m_eventManager);
            }
            catch
            {
                MessageBox.Show("Browse Failed", "Error");
                Application.Exit();
            }
        }
		//
		// ServiceFound
		//
		// Called by DNSServices core as a result of a Browse call
		//
		public void
        ServiceFound
				    (
				    DNSSDService    sref,
				    DNSSDFlags  	flags,
				    uint			ifIndex,
                    String          serviceName,
                    String          regType,
                    String          domain
				    )
		{
            if (serviceName != m_name)
            {
                PeerData peer = new PeerData();
                peer.InterfaceIndex = ifIndex;
                peer.Name = serviceName;
                peer.Type = regType;
                peer.Domain = domain;
                peer.Address = null;
                comboBox1.Items.Add(peer);
                if (comboBox1.Items.Count == 1)
                {
                    comboBox1.SelectedIndex = 0;
                }
            }
		}
        //
        // ServiceLost
        //
        // Called by DNSServices core as a result of a Browse call
        //
        public void
        ServiceLost
                    (
                    DNSSDService sref,
                    DNSSDFlags flags,
                    uint ifIndex,
                    String serviceName,
                    String regType,
                    String domain
                    )
        {
            PeerData peer = new PeerData();
            peer.InterfaceIndex = ifIndex;
            peer.Name = serviceName;
            peer.Type = regType;
            peer.Domain = domain;
            peer.Address = null;
            comboBox1.Items.Remove(peer);
        }
		//
		// ServiceResolved
		//
		// Called by DNSServices core as a result of DNSService.Resolve()
		// call
		//
        public void
        ServiceResolved
                    (
                    DNSSDService sref,
                    DNSSDFlags flags,
                    uint ifIndex,
                    String fullName,
                    String hostName,
                    ushort port,
                    TXTRecord txtRecord
                    )
		{
            m_resolver.Stop();
            m_resolver = null;
            PeerData peer = (PeerData)comboBox1.SelectedItem;
            peer.Port = port;
			//
			// Query for the IP address associated with "hostName"
			//
            try
            {
                m_resolver = m_service.QueryRecord(0, ifIndex, hostName, DNSSDRRType.kDNSSDType_A, DNSSDRRClass.kDNSSDClass_IN, m_eventManager );
            }
            catch
            {
                MessageBox.Show("QueryRecord Failed", "Error");
                Application.Exit();
            }
		}
		//
		// QueryAnswered
		//
		// Called by DNSServices core as a result of DNSService.QueryRecord()
		// call
		//
		public void
		QueryAnswered
			(
            DNSSDService    service, 
            DNSSDFlags      flags,
            uint            ifIndex,
            String          fullName,
            DNSSDRRType     rrtype,
            DNSSDRRClass    rrclass,
            Object          rdata,
            uint            ttl
            )
        {
			//
			// Stop the resolve to reduce the burden on the network
			//
            m_resolver.Stop();
            m_resolver = null;
            PeerData peer = (PeerData) comboBox1.SelectedItem;
			uint bits = BitConverter.ToUInt32( (Byte[])rdata, 0);
			System.Net.IPAddress address = new System.Net.IPAddress(bits);
            peer.Address = address;
		}
        public void
        OperationFailed
                    (
                    DNSSDService service,
                    DNSSDError error
                    )
        {
            MessageBox.Show("Operation returned an error code " + error, "Error");
        }
        //
        // OnReadMessage
        //
        // Called when there is data to be read on a socket
        //
        // This is called (indirectly) from OnReadSocket()
        //
        private void
        OnReadMessage
                (
                String msg
                )
        {
            int rgb = 0;
            for (int i = 0; i < msg.Length && msg[i] != ':'; i++)
            {
                rgb = rgb ^ ((int)msg[i] << (i % 3 + 2) * 8);
            }
            Color color = Color.FromArgb(rgb & 0x007F7FFF);
            richTextBox1.SelectionColor = color;
            richTextBox1.AppendText(msg + Environment.NewLine);
        }
		//
		// OnReadSocket
		//
		// Called by the .NET core when there is data to be read on a socket
		//
		// This is called from a worker thread by the .NET core
		//
		private void
		OnReadSocket
				(
				IAsyncResult ar
				)
		{
			try
			{
				int read = m_socket.EndReceive(ar);
				if (read > 0)
				{
					String msg = Encoding.UTF8.GetString(m_buffer, 0, read);
					Invoke(m_readMessageCallback, new Object[]{msg});
				}
				m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), this);
			}
			catch
			{
			}
		}
		public SimpleChat()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
            try
            {
                m_service = new DNSSDService();
            }
            catch
            {
                MessageBox.Show("Bonjour Service is not available", "Error");
                Application.Exit();
            }
			//
			// Associate event handlers with all the Bonjour events that the app is interested in.
			//
            m_eventManager = new DNSSDEventManager();
            m_eventManager.ServiceRegistered += new _IDNSSDEvents_ServiceRegisteredEventHandler(this.ServiceRegistered);
            m_eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
            m_eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
            m_eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
            m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
            m_eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
			//
			// Socket read handler
			//
			m_readMessageCallback = new ReadMessageCallback(OnReadMessage);
			this.Load += new System.EventHandler(this.Form1_Load);
			this.AcceptButton = button1;
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void
		Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
				if (m_registrar != null)
				{
					m_registrar.Stop();
				}
				if (m_browser != null)
				{
					m_browser.Stop();
				}
                if (m_resolver != null)
                {
                    m_resolver.Stop();
                }
                m_eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
                m_eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
                m_eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
                m_eventManager.QueryRecordAnswered -= new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
                m_eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
			}
			base.Dispose( disposing );
		}
		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.comboBox1 = new System.Windows.Forms.ComboBox();
			this.textBox2 = new System.Windows.Forms.TextBox();
			this.button1 = new System.Windows.Forms.Button();
			this.label1 = new System.Windows.Forms.Label();
			this.richTextBox1 = new System.Windows.Forms.RichTextBox();
			this.SuspendLayout();
			// 
			// comboBox1
			// 
			this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right);
			this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.comboBox1.Location = new System.Drawing.Point(59, 208);
			this.comboBox1.Name = "comboBox1";


Answer: 			this.comboBox1.Size = new System.Drawing.Size(224, 21);