using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.Descriptors.Extension;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.Dvb
{
    class DvbExtensionDescriptorConverter : IDescriptorConverter
    {
	    private readonly Tuple<ConstructorInfo, ExtensionDescriptorAttribute>[] knownDescriptors;

	    public DvbExtensionDescriptorConverter()
        {
	        knownDescriptors = PluginManager.GetInstance().GetExtensionDescriptors();
        }

        
        private const bool CRASH_ON_UNIMPLEMENTED_DESCRIPTOR = true;

        private TsDescriptor UnpackExtensionDescriptor(Dvb.Descriptors.ExtensionDescriptor extensionDescriptor, string callingTable)
        {
            if (extensionDescriptor.DescriptorTagExtension >= 0x80)
            {
                return new ExtensionUserDefinedDescriptor(extensionDescriptor.DescriptorTagExtension, extensionDescriptor.SelectorBytes);
            }
            if (knownDescriptors[extensionDescriptor.DescriptorTagExtension] == null)
            {
                string format = String.Format("Extension Descriptor 0x{0:X2} ({0}) not implemented.", extensionDescriptor.DescriptorTagExtension);
                if (CRASH_ON_UNIMPLEMENTED_DESCRIPTOR)
                    throw new NotImplementedException(format);
                else
                    Console.WriteLine(format);
                return null;
            }

            if (!knownDescriptors[extensionDescriptor.DescriptorTagExtension].Item2.Matches(callingTable))
                return null;

            object result = knownDescriptors[extensionDescriptor.DescriptorTagExtension].Item1.Invoke(new object[] { extensionDescriptor.SelectorBytes });
            return (ExtensionDescriptor)result;
        }

        public TsDescriptor Convert(TsDescriptor descriptor, string tableName)
        {
            Dvb.Descriptors.ExtensionDescriptor extensionDescriptor = descriptor as Dvb.Descriptors.ExtensionDescriptor;
            if (extensionDescriptor == null)
                throw new ArgumentException(nameof(descriptor));

            return UnpackExtensionDescriptor(extensionDescriptor, tableName);
        }
    }
}
