using CommLib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;

namespace ModuleDataLib
{
    /// <summary>
    /// Bázová třída pro odvozené třídy realizující rozhranní modulu
    /// </summary>
    public class ModuleBase : IDisposable
    {
        /// <summary>
        /// Číslo portu pro nastavování modulů (soket na tomto portu je modulem
        /// aut. ukončena 30 sec. po posledním přenosu dat)
        /// </summary>
        const UInt16 SETUP_PORT = 5002;
        /// <summary>
        /// Číslo portu pro datovou komunikaci (tento port je určen pouze pro čtení
        /// naměřených hodnot, modul uzavírá soket ihned po odeslání odpovědi)
        /// </summary>
        const UInt16 DATA_PORT = 5001;
        /// <summary>
        /// Číslo portu pro broadcast vysílání naměřených dat
        /// </summary>
        const UInt16 BC_PORT = 5000;
        /// <summary>
        /// Timeout pro TCP komunukaci
        /// </summary>
        const int TIME_OUT = 3000;
        /// <summary>
        /// Pevná část identifikátoru modulu senzoru
        /// </summary>
        const string SENSOR_HW = "MSENS";
        /// <summary>
        /// Pevná část identifikátoru modulu displeje
        /// </summary>
        const string DISPLAY_HW = "MDISP";
        /// <summary>
        /// Povel pro restart modulu
        /// </summary>
        const string RST = "RST";

        /// <summary>
        /// Odkaz na instanci komunikačního objektu
        /// </summary>
        public TcpClientComm CommObject { get; set; }       

        /// <summary>
        /// Odkaz na instanci objektu identifikační komunikace
        /// </summary>
        public DataId Id { get; set; }
        public DataNet Net { get; set; }
        public DataWlan Wlan { get; set; }

        public ModuleBase()
        {
            this.Id = new DataId(this);
            this.Net = new DataNet(this);
            this.Wlan = new DataWlan(this);
        }
      
        
        /// <summary>
        /// Metoda pro připojení modulu na základě zadané IP adresy. Vrací instanci třídy
        /// ModuleSensor nebo ModuleDisplay, podle toho, jak se cílové zařízení identifikuje.
        /// V případě neúspěchu vrací null.
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static ModuleBase Connect(IPAddress ip)
        {
            try
            {
                TcpClientComm comm = new TcpClientComm(ip, SETUP_PORT, TIME_OUT);

                ModuleBase module = new ModuleBase() { CommObject = comm };

                module.Id.Get();

                if (module.Id.HwString.StartsWith(SENSOR_HW))
                    return new ModuleSensor(module);

                if (module.Id.HwString.StartsWith(DISPLAY_HW))
                    return new ModuleDisplay(module);
            }
            catch
            {
            }
            return null;
        }

        /// <summary>
        /// Provede restart cílového modulu.
        /// </summary>
        public void Restart()
        {
            try
            {
                CommObject.SendReceive(RST);
            }
            catch
            {
            }
        }

        #region dispose

        private bool IsDisposed;

        public virtual void Dispose()
        {
             if (!this.IsDisposed)
            {
                if (CommObject != null)
                    CommObject.Close();
                this.IsDisposed = true;
            }
        }
        #endregion
    }


    /// <summary>
    /// Třída realizující rozhraní k modulu snímače
    /// </summary>
    public class ModuleSensor : ModuleBase
    {

        public DataData Data { get; set; }
        public DataMeas Meas { get; set; }

        /// <summary>
        /// Vytvoří instanci na základě instance bázové třídy
        /// </summary>
        /// <param name="module"></param>
        public ModuleSensor(ModuleBase module)
        {
            this.CommObject = module.CommObject;

            this.Id = module.Id;
            this.Net = module.Net;
            this.Wlan = module.Wlan;

            this.Data = new DataData(module);
            this.Meas = new DataMeas(module);
        }
    }

    /// <summary>
    /// Třída realizující rozhraní k modulu zobrazovače
    /// </summary>
    public class ModuleDisplay : ModuleBase
    {
        public DataSource Source { get; set; }
        public DataDisplay Display { get; set; }

        /// <summary>
        /// Vytvoří instanci na základě instance bázové třídy
        /// </summary>
        /// <param name="module"></param>
        public ModuleDisplay(ModuleBase module)
        {
            this.CommObject = module.CommObject;

            this.Id = module.Id;
            this.Net = module.Net;
            this.Wlan = module.Wlan;

            this.Source = new DataSource(module);
            this.Display = new DataDisplay(module);
        }
    }



}

