using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
{
    public class DsmCcModuleXmlMemory
    {
        private DsmCcModuleXmlMemory()
        {
            _fileInfo = new FileInfo("dsmcc.xml");
            _xmlSerializer = new XmlSerializer(typeof(List<DsmCcModuleCoordinate>));
            if (_fileInfo.Exists)
            {
                StreamReader streamReader = _fileInfo.OpenText();
                _list = (List<DsmCcModuleCoordinate>)_xmlSerializer.Deserialize(streamReader);
                streamReader.Close();
            }
            else
            {
                _list = new List<DsmCcModuleCoordinate>();
            }
        }

        private FileInfo _fileInfo;
        private XmlSerializer _xmlSerializer;
        private List<DsmCcModuleCoordinate> _list;
        private static DsmCcModuleXmlMemory _instance;
        public static DsmCcModuleXmlMemory GetInstance()
        {
            if (_instance == null)
            {
                _instance = new DsmCcModuleXmlMemory();
            }

            return _instance;
        }

        public void MarkComplete(int currentNetworkId, int currentTransportStreamId, int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
        {
            DsmCcModuleCoordinate coordinate = new DsmCcModuleCoordinate(currentNetworkId, currentTransportStreamId, elementaryPid, moduleModuleId, moduleModuleVersion);
            if (_list.Contains(coordinate))
                return;
            _list.Add(coordinate);

            FileStream fileStream = _fileInfo.OpenWrite();
            _xmlSerializer.Serialize(fileStream,_list);
            fileStream.Flush(true);
            fileStream.Close();
        }

        public bool IsWanted(int currentNetworkId, int currentTransportStreamId, int elementaryPid, ushort moduleId, byte moduleVersion)
        {
            DsmCcModuleCoordinate coordinate = new DsmCcModuleCoordinate(currentNetworkId, currentTransportStreamId, elementaryPid, moduleId, moduleVersion);
            return !_list.Contains(coordinate);
        }

        public class DsmCcModuleCoordinate
        {
            [XmlAttribute]
            public int NetworkId { get; set; }
            
            [XmlAttribute]
            public int TransportStreamId { get; set; }
            
            [XmlAttribute]
            public int Pid { get; set; }
            
            [XmlAttribute]
            public ushort ModuleId { get; set; }
            
            [XmlAttribute]
            public byte ModuleVersion { get; set; }

            public DsmCcModuleCoordinate()
            {

            }
            public DsmCcModuleCoordinate(int currentNetworkId, int currentTransportStreamId, int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
            {
                NetworkId = currentNetworkId;
                TransportStreamId = currentTransportStreamId;
                Pid = elementaryPid;
                ModuleId = moduleModuleId;
                ModuleVersion = moduleModuleVersion;
            }

            protected bool Equals(DsmCcModuleCoordinate other)
            {
                return NetworkId == other.NetworkId && TransportStreamId == other.TransportStreamId && Pid == other.Pid && ModuleId == other.ModuleId && ModuleVersion == other.ModuleVersion;
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj)) return false;
                if (ReferenceEquals(this, obj)) return true;
                if (obj.GetType() != this.GetType()) return false;
                return Equals((DsmCcModuleCoordinate)obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    var hashCode = NetworkId;
                    hashCode = (hashCode * 397) ^ TransportStreamId;
                    hashCode = (hashCode * 397) ^ Pid;
                    hashCode = (hashCode * 397) ^ ModuleId.GetHashCode();
                    hashCode = (hashCode * 397) ^ ModuleVersion.GetHashCode();
                    return hashCode;
                }
            }
        }
    }
}
