using System;
using System.Text;


namespace Wayne.Lib.Log
{
    /// <summary>
    /// Describes an alarm generated on a device.
    /// </summary>
    public class AlarmEventLogEntry: EventLogEntry
    {
        private string alarmText = null;

        /// <summary>
        /// The alarm type id.
        /// </summary>
        public AlarmId AlarmId { get; private set; }
        /// <summary>
        /// The Station number where the alarm was generated.
        /// </summary>
        public string SiteId { get; private set; }
        /// <summary>
        /// The device id on the device that generated the alarm.
        /// </summary>
        public int DeviceId { get; private set; }
        /// <summary>
        /// The date-time the alarm was generated.
        /// </summary>
        public DateTime Created { get; private set; }
        /// <summary>
        /// The Device type.
        /// </summary>
        public AlarmDeviceType DeviceType { get; private set; }       
        /// <summary>
        /// The alarm text.
        /// </summary>
        public string AlarmText
        {
            get { return alarmText ?? AlarmId.ToString(); }
            set { alarmText = value; }
        }

        /// <summary>
        /// Ctor, the default alarm text is used.
        /// </summary>
        /// <param name="alarmId">The id of the alarm</param>
        /// <param name="deviceType">The devicetype from where the alarm was generated.</param>
        /// <param name="siteId">The station number</param>
        /// <param name="deviceId">The device id where the alarm was generated.</param>
        public AlarmEventLogEntry(AlarmId alarmId, AlarmDeviceType deviceType, string siteId, int deviceId)
            : this(alarmId, deviceType, siteId, deviceId, null)
        {
        }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="alarmId">The id of the alarm</param>
        /// <param name="deviceType">The devicetype from where the alarm was generated.</param>
        /// <param name="siteId">The station number</param>
        /// <param name="deviceId">The device id where the alarm was generated.</param>
        /// <param name="alarmText">To override the default Alarm text</param>
        public AlarmEventLogEntry(AlarmId alarmId, AlarmDeviceType deviceType, string siteId, int deviceId, string alarmText)
            : base(new IdentifiableEntity(IdentifiableEntity.NoId, "AlarmEvent", string.Empty, null), alarmId)
        {
            AlarmId = alarmId;
            SiteId = siteId;
            DeviceId = deviceId;
            Created = DateTime.Now;
            DeviceType = deviceType;
            AlarmText = alarmText;
        }
        
        /// <summary>
        /// Used to generate Alarm Event logfiles.
        /// </summary>
        /// <param name="separator">The separator to use to seperate log entries</param>
        /// <returns>A formatted representation of the log entry</returns>
        public string GetLogLine(string separator)
        {
            var output = new StringBuilder();

            //output.Append(SiteId.Substring(Math.Max(0, SiteId.Length-4), 4).PadLeft(4, '0'));
            output.Append(Prepare(SiteId, 4, '0'));
            output.Append(separator);

            output.Append(Created.ToString("yyyy-MM-dd HH:mm:ss"));
            output.Append(separator);

            output.Append(Prepare(DeviceType, 1, '0'));
            output.Append(separator);

            output.Append(Prepare(DeviceId, 2, '0'));
            output.Append(separator);

            output.Append(Prepare(AlarmId, 4, '0'));
            output.Append(separator);

            output.Append(Prepare(AlarmText, 40, ' ', PadDirection.Right));

            return output.ToString();
        }

        /// <summary>
        /// Overrides object.ToString()
        /// </summary>
        /// <returns>A readable representation of the log entry.</returns>
        public override string ToString()
        {
            var sb = new StringBuilder();

            sb.Append("Alarm event ");
            sb.Append(AlarmId.ToString("D"));
            sb.Append(" signalled from device type ");
            sb.Append(DeviceType.ToString());
            sb.Append(", station ");
            sb.Append(SiteId.PadLeft(4, '0'));
            sb.Append(", device ");
            sb.Append(DeviceId.ToString("D").PadLeft(2, '0'));
            sb.Append(" at ");
            sb.Append(Created.ToString("yyyy-MM-dd HH:mm:ss"));

            return sb.ToString();

        }

        private enum PadDirection
        {
            Left,
            Right
        }

        private static string Prepare(string original, int length, char paddingCharacter, PadDirection padDirection)
        {
            return padDirection == PadDirection.Left
                       ? original.PadLeft(length, paddingCharacter).Substring(Math.Max(0, original.Length - length))
                       : original.PadRight(length, paddingCharacter).Substring(Math.Max(0, original.Length - length));
        }

        private static string Prepare(string original, int length, char paddingCharacter)
        {
            return Prepare(original, length, paddingCharacter, PadDirection.Left);
        }

        private static string Prepare(int original, int length, char paddingCharacter)
        {
            return Prepare(original.ToString("D"), length, paddingCharacter);
        }

        private static string Prepare(Enum original, int length, char paddingCharacter)
        {
            return Prepare(original.ToString("D"), length, paddingCharacter);
        }
    }
}