// Created with MonoDevelop
//
//    Copyright (C) 2019 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;

using Hiperscan.Unix;


namespace Hiperscan.SGS.Common
{

    [Serializable()]
    public class Version : System.Runtime.Serialization.ISerializable
    {
        public enum VersionRequestType : byte
        {
            Protocol = 0,
            Firmware = 1,
            ScanEngine = 2,
            Hardware = 4,
        }

        public enum VersionId : ushort
        {
            v0_0 = (0 << 8) + 0,
            v0_10 = (0 << 8) + 10,
            v0_11 = (0 << 8) + 11,
            v0_12 = (0 << 8) + 12,
            v0_13 = (0 << 8) + 13,
            v0_14 = (0 << 8) + 14,
            v0_15 = (0 << 8) + 15,
            v0_16 = (0 << 8) + 16,
            v0_17 = (0 << 8) + 17,
            v0_18 = (0 << 8) + 18,
            v0_19 = (0 << 8) + 19,
            v0_20 = (0 << 8) + 20,
            v0_21 = (0 << 8) + 21,

            v199_21 = (199 << 8) + 21,

            v200_22 = (200 << 8) + 22,
            v200_255 = (200 << 8) + 255,

            v201_0 = (201 << 8) + 0,

            v1_0 = (1 << 8) + 0,
            v1_1 = (1 << 8) + 1,
            v1_2 = (1 << 8) + 2,
            v1_5 = (1 << 8) + 5,
            v1_6 = (1 << 8) + 6,

            NSeries = ushort.MaxValue
        }

        private readonly byte major;
        private readonly byte minor;

        public Version(byte major, byte minor)
        {
            this.major = major;
            this.minor = minor;
        }

        public Version(ushort id)
        {
            this.major = (byte)((id >> 8) & 0xFF);
            this.minor = (byte)(id & 0xFF);
        }

        public Version(SerializationInfo info, StreamingContext context)
        {
            this.major = (byte)info.GetValue("Major", typeof(byte));
            this.minor = (byte)info.GetValue("Minor", typeof(byte));
        }

        public Version(string version)
        {
            if (string.IsNullOrEmpty(version))
            {
                this.minor = 0;
                this.major = 0;
            }
            else
            {
                string[] split = Regex.Split(version, @"\.");
                if (split.Length < 2 || split.Length > 3)
                    throw new FormatException(Catalog.GetString("Invalid version format:") + " " + version);
                this.major = byte.Parse(split[0]);
                this.minor = byte.Parse(split[1]);
            }
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Major", this.major);
            info.AddValue("Minor", this.minor);
        }

        public override string ToString()
        {
            if (this.Id == 0)
                return Catalog.GetString("n/a");
            return string.Format("{0}.{1} (ID {2})", this.Major, this.Minor, this.Id);
        }

        public uint Major
        {
            get { return this.major; }
        }

        public uint Minor
        {
            get { return this.minor; }
        }

        public ushort Id
        {
            get { return (ushort)((this.major << 8) + this.minor); }
        }

        public byte[] AsByteBuffer
        {
            get
            {
                byte[] version_buffer = new byte[2];
                version_buffer[0] = (byte)this.Major;
                version_buffer[1] = (byte)this.Minor;
                return version_buffer;
            }
        }
    }
}
