using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using skyscraper2.TsDuckInterface;
using skyscraper2.TsDuckInterface.DvbModel;
using skyscraper2.TsDuckInterface.Inputs;
using skyscraper2.TsDuckInterface.Outputs;
using skyscraper2.TsDuckInterface.Processors;

namespace skyscraper5.Skyscraper
{
    class TspBatchCapture
    {
        public TspBatchCapture()
        {
            xmlSerializer = new XmlSerializer(typeof(List<string>));
        }

        private XmlSerializer xmlSerializer;

        private List<string> GetDedupList()
        {
            if (!File.Exists("dedup.xml"))
                return new List<string>();

            FileStream fileStream = File.OpenRead("dedup.xml");
            List<string> result = (List<string>)xmlSerializer.Deserialize(fileStream);
            fileStream.Close();
            return result;
        }

        private void SaveDedupList(List<string> list)
        {
            FileStream fileStream = File.OpenWrite("dedup.xml");
            xmlSerializer.Serialize(fileStream, list);
            fileStream.Close();
        }

        public void Run(FileInfo fi, int adapterNo, int satNo, string satName)
        {
            List<string> dedupList = GetDedupList();
            StreamReader streamReader = fi.OpenText();
            string line = null;
            while (!streamReader.EndOfStream)
            {
                string readLine = streamReader.ReadLine();
                if (readLine.StartsWith("#"))
                    continue;
                string[] args = readLine.Split(' ');
                if (args.Length != 8)
                    continue;

                string inputDeliverySystem = args[0];
                long frequency = Convert.ToInt64(args[1]);
                char polarity = args[2][0];
                long symbolRate = Convert.ToInt64(args[3]);
                string fec = args[4];
                double rollOff = Convert.ToDouble(String.Format("0,{0}", args[5]));
                string modulation = args[6];
                long flags = Convert.ToInt64(args[7]);

                DvbInput dvbInput = new DvbInput();
                dvbInput.Frequency = frequency * 1000;
                dvbInput.SymbolRate = symbolRate;
                dvbInput.AdapterId = (byte)adapterNo;
                dvbInput.DeliverySystem = DeliverySystem.FromString(inputDeliverySystem);
                dvbInput.Lnb = Lnb.Extended;
                dvbInput.Polarity = GetPolarity(polarity);
                dvbInput.SatelliteNumber = (byte)satNo;

                DirectoryInfo di = new DirectoryInfo("E:\\tspBatchCapture");
                if (!di.Exists)
                    di.Create();
                string fileName = String.Format("{0}_{1}_{2}_{3}.ts", satName, frequency / 1000, polarity, symbolRate / 1000);
                if (dedupList.Contains(fileName))
                    continue;
                FileInfo outputFileInfo = new FileInfo(Path.Combine(di.FullName, fileName));
                FileOutput fileOutput = new FileOutput(outputFileInfo);

                UntilProcessor untilProcessor = new UntilProcessor();
                untilProcessor.Bytes = 100000000L;  //100 MB

                TspCommandBuilder tspCommandBuilder = new TspCommandBuilder();
                tspCommandBuilder.Verbose = true;
                tspCommandBuilder.TspPath = "tsp";
                tspCommandBuilder.Input = dvbInput;
                tspCommandBuilder.Output = fileOutput;
                tspCommandBuilder.Processors.Add(untilProcessor);
                int exitCode = tspCommandBuilder.ExecuteAndWait();
                switch (exitCode)
                {
                    case 0:
                        dedupList.Add(fileName);
                        SaveDedupList(dedupList);
                        break;
                    case -1073741819:
                        dvbInput.DeliverySystem = FlipDeliverySystem(dvbInput.DeliverySystem);
                        tspCommandBuilder.ExecuteAndWait();
                        dedupList.Add(fileName);
                        SaveDedupList(dedupList);
                        break;
                    default:
                        throw new NotImplementedException(exitCode.ToString());
                }

                Thread.Sleep(1000);
            }
        }

        private Polarity GetPolarity(char c)
        {
            if (c == 'H')
                return Polarity.Horizontal;
            else if (c == 'V')
                return Polarity.Vertical;
            else
                throw new NotImplementedException(c.ToString());
        }

        private DeliverySystem FlipDeliverySystem(DeliverySystem ds)
        {
            if (ds.Equals(DeliverySystem.DVB_S))
                return DeliverySystem.DVB_S2;
            if (ds.Equals(DeliverySystem.DVB_S2))
                return DeliverySystem.DVB_S;
            throw new NotImplementedException(ds.ToString());
        }
    }
}
