// Created with MonoDevelop
//
//    Copyright (C) 2023 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 Hiperscan.SGS.Common;
using Hiperscan.SGS.Splitter;
using static Hiperscan.SGS.Common.Version;
using Version = Hiperscan.SGS.Common.Version;

namespace Hiperscan.SGS.SerialInterface.USB
{
    public partial class RaspianCom
    {
        internal static VersionInfo GetVersionInfo(DeviceInfo device_info, bool disable_timeout)
        {
            RaspianCom raspian_com = new RaspianCom(device_info, true);
            raspian_com.OpenBySerialNumber(device_info.SerialNumber);

            int timeout = SplitterProtocol.BLOCK_INTERVAL;
            if (disable_timeout == false)
                timeout += (int)RaspianCom.MIN_TIMEOUT;

            // protocol version
            byte[] pv_buf = new byte[] { 0, 0 };
            for (int count = 0; count < 20; ++count)
            {
                try
                {
                    raspian_com.Write(new byte[] { (byte)VersionRequestType.Protocol });
                    pv_buf = raspian_com.ReadBlocking(2, timeout, null);
                    break;
                }
                catch (Exception ex) when (ex is TimeoutException)
                {
                    if (timeout == 0)
                        break;
                }
            }

            Version protocol_version = new Version(pv_buf[0], pv_buf[1]);

            byte[] fw_buf = new byte[] { 0, 0 };
            byte[] se_buf = new byte[] { 0, 0 };
            byte[] hw_buf = new byte[] { 0, 0 };

            // firmware version
            raspian_com.Write(new byte[] { (byte)VersionRequestType.Firmware });
            fw_buf = raspian_com.ReadBlocking(2, timeout, null);

            // scan engine version
            raspian_com.Write(new byte[] { (byte)VersionRequestType.ScanEngine });
            se_buf = raspian_com.ReadBlocking(2, timeout, null);

            // hardware version
            raspian_com.Write(new byte[] { (byte)VersionRequestType.Hardware });
            hw_buf = raspian_com.ReadBlocking(2, timeout, null);

            raspian_com.Close();

            Console.WriteLine("Protocol version: {0}.{1}", pv_buf[0], pv_buf[1]);
            Console.WriteLine("Firmware version: {0}.{1}", fw_buf[0], fw_buf[1]);
            Console.WriteLine("Scan Engine version: {0}.{1}", se_buf[0], se_buf[1]);
            Console.WriteLine("Hardware version: {0}.{1}", hw_buf[0], hw_buf[1]);

            Version firmware_version = new Version(fw_buf[0], fw_buf[1]);
            Version scan_engine_version = new Version(se_buf[0], se_buf[1]);
            Version hardware_version = new Version(hw_buf[0], hw_buf[1]);

            return new VersionInfo(protocol_version, firmware_version, scan_engine_version, hardware_version);
        }
    }
}
