
using MySqlConnector;
using skyscraper5.Mhp.Si;
using skyscraper5.Mhp.Si.Model;
using System.Collections.Generic;
using System.Data;
using skyscraper5.Mhp.Descriptors;
using skyscraper5.Mhp.Descriptors.InteractionTransportSelectors;
using System;
using skyscraper5.Teletext;
using skyscraper8.DvbI;
using skyscraper8.DvbNip;
using skyscraper8.Ses;
using skyscraper8.Skyscraper.Scraper.Storage;

namespace skyscraper5.Data.MySql
{
    public partial class MySqlDataStorage : DataStorage
    {
        private HashSet<ApplicationIdentifier> _knownAits;

        private void InsertAitAppNames(MySqlTransaction transaction, AitApplication aitApplication)
        {
            if (aitApplication.ApplicationName == null)
                return;

            if (aitApplication.ApplicationName.Count == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_application_names (org_id, app_id, lang, name) VALUES (@org_id,@app_id,@lang,@name)";
            command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@lang", MySqlDbType.VarChar);
            command.Parameters.Add("@name", MySqlDbType.VarChar);
            foreach (KeyValuePair<string, string> keyValuePair in aitApplication.ApplicationName)
            {
                command.Parameters["@lang"].Value = keyValuePair.Key;
                command.Parameters["@name"].Value = keyValuePair.Value;
                command.ExecuteNonQuery();
            }
        }

        private void InsertAitAppProfiles(MySqlTransaction transaction, AitApplication aitApplication)
        {
            if (aitApplication.ApplicationProfiles == null)
                return;

            if (aitApplication.ApplicationProfiles.Length == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_application_profiles (org_id, app_id, app_profile, major, minor, micro) VALUES (@org_id, @app_id, @app_profile, @major, @minor, @micro)";
            command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@app_profile", DbType.Int32);
            command.Parameters.Add("@major", MySqlDbType.Int16);
            command.Parameters.Add("@minor", MySqlDbType.Int16);
            command.Parameters.Add("@micro", MySqlDbType.Int16);
            foreach (ApplicationDescriptor.ApplicationProfileEncoding profile in aitApplication.ApplicationProfiles)
            {
                command.Parameters["@app_profile"].Value = profile.ApplicationProfile;
                command.Parameters["@major"].Value = profile.Major;
                command.Parameters["@minor"].Value = profile.Minor;
                command.Parameters["@micro"].Value = profile.Micro;
                command.ExecuteNonQuery();
            }
        }

        private void InsertAitBoundaryExtensions(MySqlTransaction transaction, AitApplication aitApplication)
        {
            if (aitApplication.BoundaryExtensions == null)
                return;
            if (aitApplication.BoundaryExtensions.Length == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_boundary_extensions (org_id, app_id, extension) VALUES (@org_id, @app_id, @extension)";
            command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@extension", MySqlDbType.VarChar);
            foreach (string extension in aitApplication.BoundaryExtensions)
            {
                command.Parameters["@extension"].Value = extension;
                command.ExecuteNonQuery();
            }
        }

        private void InsertAitExternalAuthorizations(MySqlTransaction transaction, AitApplication aitApplication)
        {
            if (aitApplication.ExternalAuthorizations == null)
                return;
            if (aitApplication.ExternalAuthorizations.Length == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_external_authorization (org_id, app_id, ext_org_id, ext_app_id, app_priority) VALUES (@org_id, @app_id, @ext_org_id, @ext_app_id, @app_priority)";
            command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@ext_org_id", MySqlDbType.Int32);
            command.Parameters.Add("@ext_app_id", MySqlDbType.Int32);
            command.Parameters.Add("@app_priority", MySqlDbType.Int16);
            foreach (ExternalApplicationAuthorisationDescriptor.ExternalAuthorization externalAuthorization in
                     aitApplication.ExternalAuthorizations)
            {
                command.Parameters["@ext_org_id"].Value = externalAuthorization.OrganisationId;
                command.Parameters["@ext_app_id"].Value = externalAuthorization.ApplicationId;
                command.Parameters["@app_priority"].Value = externalAuthorization.ApplicationPriority;
                command.ExecuteNonQuery();
            }
        }

        private void InsertAitTransportProtocols(MySqlTransaction transaction, AitApplication aitApplication)
        {
            if (aitApplication.TransportProtocols == null)
                return;
            if (aitApplication.TransportProtocols.Count == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_transport_protocols (org_id, app_id, protocol_id, transport_protocol_label, remote_connection, original_network_id, transport_stream_id, service_id, component_tag, url_base) " +
                "VALUES " +
                "(@org_id, @app_id, @protocol_id, @transport_protocol_label, @remote_connection, @original_network_id, @transport_stream_id, @service_id, @component_tag, @url_base)";
            command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@protocol_id", MySqlDbType.Int32);
            command.Parameters.Add("@transport_protocol_label", MySqlDbType.Int16);
            command.Parameters.Add("@remote_connection", MySqlDbType.Bool);
            command.Parameters.Add("@original_network_id", MySqlDbType.Int32);
            command.Parameters.Add("@transport_stream_id", MySqlDbType.Int32);
            command.Parameters.Add("@service_id", MySqlDbType.Int32);
            command.Parameters.Add("@component_tag", MySqlDbType.Int16);
            command.Parameters.Add("@url_base", MySqlDbType.VarChar);
            foreach (TransportProtocolDescriptor protocol in aitApplication.TransportProtocols)
            {
                command.Parameters["@protocol_id"].Value = protocol.ProtocolId;
                command.Parameters["@transport_protocol_label"].Value = protocol.TransportProtocolLabel;
                switch (protocol.ProtocolId)
                {
                    case 1:
                        ObjectCarouselTransportSelector octs = (ObjectCarouselTransportSelector)protocol.Selector;
                        command.Parameters["@remote_connection"].Value = octs.RemoteConnection;
                        command.Parameters["@original_network_id"].Value = octs.OriginalNetworkId;
                        command.Parameters["@transport_stream_id"].Value = octs.TransportStreamId;
                        command.Parameters["@service_id"].Value = octs.ServiceId;
                        command.Parameters["@component_tag"].Value = octs.ComponentTag;
                        command.Parameters["@url_base"].Value = DBNull.Value;
                        command.ExecuteNonQuery();
                        break;
                    case 3:
                        InteractionTransportSelector its = (InteractionTransportSelector)protocol.Selector;
                        command.Parameters["@remote_connection"].Value = DBNull.Value;
                        command.Parameters["@original_network_id"].Value = DBNull.Value;
                        command.Parameters["@transport_stream_id"].Value = DBNull.Value;
                        command.Parameters["@service_id"].Value = DBNull.Value;
                        command.Parameters["@component_tag"].Value = DBNull.Value;
                        command.Parameters["@url_base"].Value = its.UrlBase;
                        command.ExecuteNonQuery();
                        InsertAitTransportProtocolUrlExtensions(transaction, aitApplication.ApplicationIdentifier, its);
                        break;
                    default:
                        throw new NotImplementedException(String.Format(protocol.ProtocolId.ToString()));
                }
            }
        }

        private void InsertAitTransportProtocolUrlExtensions(MySqlTransaction transaction, ApplicationIdentifier aitApplicationApplicationIdentifier, InteractionTransportSelector its)
        {
            if (its.UrlExtensions == null)
                return;
            if (its.UrlExtensions.Length == 0)
                return;

            MySqlCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            command.CommandText =
                "INSERT INTO dvb_ait_transport_protocols_url_extensions (org_id, app_id, ordinal, url_extension) VALUES (@org_id, @app_id, @ordinal, @url_extensiion)";
            command.Parameters.AddWithValue("@org_id", aitApplicationApplicationIdentifier.OrganisationId);
            command.Parameters.AddWithValue("@app_id", aitApplicationApplicationIdentifier.ApplicationId);
            command.Parameters.Add("@ordinal", MySqlDbType.Int32);
            command.Parameters.Add("@url_extensiion", MySqlDbType.VarChar);
            for (int i = 0; i < its.UrlExtensions.Length; i++)
            {
                command.Parameters["@ordinal"].Value = i;
                command.Parameters["@url_extensiion"].Value = its.UrlExtensions[i];
                command.ExecuteNonQuery();
            }
        }

		public bool TestForAitApplication(ApplicationIdentifier aitApplicationApplicationIdentifier)
		{
			if (_knownAits == null)
				_knownAits = new HashSet<ApplicationIdentifier>();

			if (_knownAits.Contains(aitApplicationApplicationIdentifier))
				return true;

			using (MySqlConnection connection = new MySqlConnection(_mcsb.ToString()))
			{
				connection.Open();
				MySqlCommand command = connection.CreateCommand();
				command.CommandText = "SELECT dateadded FROM dvb_ait WHERE app_id = @app AND org_id = @org";
				command.Parameters.AddWithValue("@app", aitApplicationApplicationIdentifier.ApplicationId);
				command.Parameters.AddWithValue("@org", aitApplicationApplicationIdentifier.OrganisationId);
				MySqlDataReader dataReader = command.ExecuteReader();
				bool result = dataReader.Read();
				if (result)
					_knownAits.Add(aitApplicationApplicationIdentifier);
				dataReader.Close();
				connection.Close();
				return result;
			}
		}

		public void StoreAitApplication(AitApplication aitApplication)
		{
			using (MySqlConnection connection = new MySqlConnection(_mcsb.ToString()))
			{
				connection.Open();
				MySqlTransaction transaction = connection.BeginTransaction();
				MySqlCommand command = connection.CreateCommand();
				command.Transaction = transaction;
				command.CommandText =
					"INSERT INTO dvb_ait (org_id, app_id, app_control_code, app_priority, service_bound_flag, transport_protocol_label, visibility, initial_path, app_usage_code, jvm_arguments, jvm_base_directory, jvm_class_path_extension, jvm_initial_class, version, is_launchable_from_older_version, launchable_completely_from_cache, not_launchable_from_broadcast, application_storage_priority, storage_property, auto_select, service_id, service_name, version_number, launch_order, storage_priority, ip_connection_required)" +
					"VALUES " +
					"(@org_id, @app_id, @app_control_code, @app_priority, @service_bound_flag, @transport_protocol_label, @visibility, @initial_path, @app_usage_code, @jvm_arguments, @jvm_base_directory, " +
					" @jvm_class_path_extension, @jvm_initial_class, @version, @is_launchable_from_older_version, @launchable_completely_from_cache, @not_launchable_from_broadcast, " +
					" @application_storage_priority, @storage_property, @auto_select, @service_id, @service_name, @version_number, @launch_order, @storage_priority, @ip_connection_required)";
				command.Parameters.AddWithValue("@org_id", aitApplication.ApplicationIdentifier.OrganisationId);
				command.Parameters.AddWithValue("@app_id", aitApplication.ApplicationIdentifier.ApplicationId);
				command.Parameters.AddWithValue("@app_control_code", aitApplication.ApplicationControlCode);
				command.Parameters.AddWithValue("@app_priority", aitApplication.ApplicationPriority);
				command.Parameters.AddWithValue("@service_bound_flag", aitApplication.ServiceBoundFlag);
				command.Parameters.AddWithValue("@transport_protocol_label", aitApplication.TransportProtocolLabel);
				command.Parameters.AddWithValue("@visibility", aitApplication.Visibility);
				command.Parameters.AddWithValue("@initial_path", aitApplication.InitialPath);
				command.Parameters.AddWithValue("@app_usage_code", aitApplication.ApplicationUsageCode);
				if (aitApplication.JvmArguments != null)
					command.Parameters.AddWithValue("@jvm_arguments", String.Join(' ', aitApplication.JvmArguments));
				else
					command.Parameters.AddWithValue("@jvm_arguments", DBNull.Value);
				command.Parameters.AddWithValue("@jvm_base_directory", aitApplication.JvmBaseDirectory);
				command.Parameters.AddWithValue("@jvm_class_path_extension", aitApplication.JvmClassPathExtension);
				command.Parameters.AddWithValue("@jvm_initial_class", aitApplication.JvmInitialClass);
				command.Parameters.AddWithValue("@version", aitApplication.Version);
				command.Parameters.AddWithValue("@is_launchable_from_older_version", aitApplication.IsLaunchableFromOlderVersion);
				command.Parameters.AddWithValue("@launchable_completely_from_cache", aitApplication.LaunchableCompletelyFromCache);
				command.Parameters.AddWithValue("@not_launchable_from_broadcast", aitApplication.NotLaunchableFromBroadcast);
				command.Parameters.AddWithValue("@application_storage_priority", aitApplication.ApplicationStoragePriority);
				command.Parameters.AddWithValue("@storage_property", aitApplication.StoragePriority);
				command.Parameters.AddWithValue("@auto_select", aitApplication.AutoSelect);
				command.Parameters.AddWithValue("@service_id", aitApplication.ServiceId);
				command.Parameters.AddWithValue("@service_name", aitApplication.ServiceName);
				command.Parameters.AddWithValue("@version_number", aitApplication.VersionNumber);
				command.Parameters.AddWithValue("@launch_order", aitApplication.LaunchOrder);
				command.Parameters.AddWithValue("@storage_priority", aitApplication.StoragePriority);
				command.Parameters.AddWithValue("@ip_connection_required", aitApplication.IpConnectionRequired);
				command.ExecuteNonQuery();

				InsertAitAppNames(transaction, aitApplication);
				InsertAitAppProfiles(transaction, aitApplication);
				InsertAitBoundaryExtensions(transaction, aitApplication);
				InsertAitExternalAuthorizations(transaction, aitApplication);
				InsertAitTransportProtocols(transaction, aitApplication);
				transaction.Commit();
				connection.Close();
				_knownAits.Add(aitApplication.ApplicationIdentifier);
			}
		}

		public bool TestForSgtList(SgtList list)
		{
			throw new NotImplementedException();
		}

		public void InsertSgtList(SgtList list)
		{
			throw new NotImplementedException();
		}

		public bool TestForSgtService(SgtService child)
		{
			throw new NotImplementedException();
		}

		public void InsertSgtService(SgtService child)
		{
			throw new NotImplementedException();
		}

		public void InsertDvbiService(DvbIService service)
		{
			throw new NotImplementedException();
		}

		public bool TestForDvbiServiceList(string id)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipPrivateDataSpecifier(NipActualCarrierInformation currentCarrierInformation, DateTime versionUpdate,
			uint privateDataSpecifier, List<string> privateDataSessions)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipTestForNetwork(BroadcastNetworkType network)
		{
			throw new NotImplementedException();
		}

		public void DvbNipInsertNetwork(BroadcastNetworkType network)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipTestForService(BroadcastMediaStreamType broadcastMediaStreamType)
		{
			throw new NotImplementedException();
		}

		public void DvbNipInsertService(BroadcastMediaStreamType broadcastMediaStreamType)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipTestForMulticastSession(MulticastSessionType multicastSession)
		{
			throw new NotImplementedException();
		}

		public void DvbNipInsertMulticastSession(MulticastSessionType multicastSession)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipTestForMulticastGatewayConfigurationTransportSession(NipActualCarrierInformation carrier,
			MulticastEndpointAddressType multicastEndpointAddressType)
		{
			throw new NotImplementedException();
		}

		public void DvbNipInsertMulticastGatewayConfigurationTransportSession(NipActualCarrierInformation carrier,
			MulticastEndpointAddressType multicastGatewayConfigurationTransportSession)
		{
			throw new NotImplementedException();
		}

		public bool DvbNipTestForCarrier(NipActualCarrierInformation currentCarrierInformation)
		{
			throw new NotImplementedException();
		}

		public void DvbNipInsertCarrier(NipActualCarrierInformation currentCarrierInformation)
		{
			throw new NotImplementedException();
		}

		public void InsertDvbiServiceListEntryPoint(long sourceHash)
		{
			throw new NotImplementedException();
		}

		public bool TestForDvbiService(string id)
		{
			throw new NotImplementedException();
		}

		public bool TestForDvbiServiceListEntryPoints(long sourceHash)
		{
			throw new NotImplementedException();
		}

		public void UpdateDvbiService(DvbIService service)
		{
			throw new NotImplementedException();
		}

		public void UpdateDvbiServiceListEntryPointUpdateDate(long hash, DateTime currentTime)
		{
			throw new NotImplementedException();
		}

		public void UpdateDvbiServiceListLastCheckedDate(string id, DateTime currentTime)
		{
			throw new NotImplementedException();
		}

		public int GetDvbiServiceVersion(string id)
		{
			throw new NotImplementedException();
		}

		public DateTime GetLastDvbiServiceListEntryPointUpdateDate(long sourceHash)
		{
			throw new NotImplementedException();
		}

		public void AddDvbiServiceToServiceList(string id, string serviceListId)
		{
			throw new NotImplementedException();
		}

		public DateTime GetDvbiServiceListLastUpdateDate(string id)
		{
			throw new NotImplementedException();
		}

		public void AddDvbiServiceListToServiceListEntryPoint(DvbiServiceList serviceList, long sourceHash)
		{
			throw new NotImplementedException();
		}

		public bool TestForServiceListEntryPoints(long sourceHash)
		{
			throw new NotImplementedException();
		}

		public void InsertDvbiServiceList(DvbiServiceList serviceList)
		{
			throw new NotImplementedException();
		}
    }
}
