using System;
using System.Globalization;
namespace Renci.SshNet.Messages.Connection
{
    /// 
    /// Represents SSH_MSG_CHANNEL_OPEN message.
    /// 
    [Message("SSH_MSG_CHANNEL_OPEN", 90)]
    public class ChannelOpenMessage : ChannelMessage
    {
        /// 
        /// Gets the type of the channel.
        /// 
        /// 
        /// The type of the channel.
        /// 
        public string ChannelType
        {
            get
            {
                return this.Info.ChannelType;
            }
        }
        /// 
        /// Gets the initial size of the window.
        /// 
        /// 
        /// The initial size of the window.
        /// 
        public uint InitialWindowSize { get; private set; }
        /// 
        /// Gets the maximum size of the packet.
        /// 
        /// 
        /// The maximum size of the packet.
        /// 
        public uint MaximumPacketSize { get; private set; }
        /// 
        /// Gets channel specific open information.
        /// 
        public ChannelOpenInfo Info { get; private set; }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        public ChannelOpenMessage()
        {
            //  Required for dynamicly loading request type when it comes from the server
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The channel number.
        /// Initial size of the window.
        /// Maximum size of the packet.
        /// The info.
        public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maximumPacketSize, ChannelOpenInfo info)
        {
            this.LocalChannelNumber = channelNumber;
            this.InitialWindowSize = initialWindowSize;
            this.MaximumPacketSize = maximumPacketSize;
            this.Info = info;
        }
        /// 
        /// Called when type specific data need to be loaded.
        /// 
        protected override void LoadData()
        {
            var channelName = this.ReadAsciiString();
            this.LocalChannelNumber = this.ReadUInt32();
            this.InitialWindowSize = this.ReadUInt32();
            this.MaximumPacketSize = this.ReadUInt32();
            var bytes = this.ReadBytes();
            if (channelName == SessionChannelOpenInfo.NAME)
            {
                this.Info = new SessionChannelOpenInfo();
            }
            else if (channelName == X11ChannelOpenInfo.NAME)
            {
                this.Info = new X11ChannelOpenInfo();
            }
            else if (channelName == DirectTcpipChannelInfo.NAME)
            {
                this.Info = new DirectTcpipChannelInfo();
            }
            else if (channelName == ForwardedTcpipChannelInfo.NAME)
            {
                this.Info = new ForwardedTcpipChannelInfo();
            }
            else
            {
                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Channel type '{0}' is not supported.", channelName));
            }
            this.Info.Load(bytes);
        }
        /// 
        /// Called when type specific data need to be saved.
        /// 
        protected override void SaveData()
        {
            this.WriteAscii(this.ChannelType);
            this.Write(this.LocalChannelNumber);
            this.Write(this.InitialWindowSize);
            this.Write(this.MaximumPacketSize);
            this.Write(this.Info.GetBytes());
        }
    }
}