using System.IO;
using System.Text;
using Platform101XP.Editor.Settings.Repositories;
using UnityEngine;

namespace Platform101XP.Editor.Settings.Export
{
    public sealed class AndroidSettingsExporter : BaseSettingsExporter
    {


        private readonly AndroidSettingsRepository androidSettings;

        public AndroidSettingsExporter(BaseSettingsRepository baseSettings, AndroidSettingsRepository androidSettings)
            : base(baseSettings)
        {
            this.androidSettings = androidSettings;
        }

        public override void Export()
        {
            // Target path for Android setting files.
            const string ANDROID_MANIFEST_TARGET_FILE = "Assets/Plugins/Android/P101XP.androidlib/AndroidManifest.xml";
            const string RESOURCES_TARGET_FILE = "Assets/Plugins/Android/P101XP.androidlib/res/values/strings.xml";
            // Build android manifest file.
            BuildAndroidManifestFile(ANDROID_MANIFEST_TARGET_FILE);
            // Build android manifest's resources file.
            BuildResourcesFile(RESOURCES_TARGET_FILE);
            // Write parameters to files.
            WriteParameterIntoFile(ANDROID_MANIFEST_TARGET_FILE);
            WriteParameterIntoFile(RESOURCES_TARGET_FILE);
        }

        private void BuildResourcesFile(string targetPath)
        {
            // Source path
            const string ANDROID_SETTINGS_TEMPLATE_FILE = "Assets/Platform101XP/Templates/stringsTemplate.xml";

            // Create parent directory if not exists (can happen)
            var directory = Path.GetDirectoryName(targetPath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            File.Copy(ANDROID_SETTINGS_TEMPLATE_FILE, targetPath, true);
            Debug.Log($"[P101XP] The Android's resources file has been saved.\nPath: {targetPath}");
        }

        private void BuildAndroidManifestFile(string targetPath)
        {
            // File paths of text components that used to build AndroidManifest.xml file.
            const string BASE_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/Root.xml";
            const string ADJUST_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/Adjust.xml";
            const string ZENDESK_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/Zendesk.xml";
            const string OK_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/OK.xml";
            const string FACEBOOK_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/Facebook.xml";
            const string IMEI_PERMISSIONS_TEMPLATE = "Assets/Platform101XP/Templates/AndroidManifest/AppsFlyer_IMEI_permissios.xml";

            // Special placeholders that used to build AndroidManifest.xml file by replacing its text components.
            const string ROOT_PLACEHOLDER = "{root}";
            const string PERMISSIONS_ROOT_PLACEHOLDER = "{permissions_root}";

            // Asserts.
            if (!File.Exists(BASE_TEMPLATE) ||
                !File.Exists(ADJUST_TEMPLATE) ||
                !File.Exists(ZENDESK_TEMPLATE) ||
                !File.Exists(OK_TEMPLATE) ||
                !File.Exists(FACEBOOK_TEMPLATE))
            {
                Debug.LogError("[P101XP] One or more AndroidManifest template files have not been found!");
                return;
            }

            // Root placeholder.
            var content = new StringBuilder();
            if (BaseSettings.ZendeskEnabled)
            {
                var text = File.ReadAllText(ZENDESK_TEMPLATE);
                content.AppendLine(text);
            }

            if (androidSettings.FacebookEnabled)
            {
                var text = File.ReadAllText(FACEBOOK_TEMPLATE);
                content.AppendLine(text);
            }

            if (androidSettings.OkEnabled)
            {
                var text = File.ReadAllText(OK_TEMPLATE);
                content.AppendLine(text);
            }

            if (androidSettings.EnableAdjust)
            {
                var text = File.ReadAllText(ADJUST_TEMPLATE);
                content.AppendLine(text);
            }


            var root = File.ReadAllText(BASE_TEMPLATE);
            var androidManifestText = root.Replace(ROOT_PLACEHOLDER, content.ToString());

            // Permissions placeholder.
            var permissionsContent = new StringBuilder();
            if (androidSettings.IMEISendingEnabled)
            {
                var text = File.ReadAllText(IMEI_PERMISSIONS_TEMPLATE);
                permissionsContent.AppendLine(text);
            }

            androidManifestText = androidManifestText.Replace(PERMISSIONS_ROOT_PLACEHOLDER, permissionsContent.ToString());

            // Create parent directory if not exists (shouldn't happen here)
            var directory = Path.GetDirectoryName(targetPath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            // Write file
            File.WriteAllText(targetPath, androidManifestText);
            Debug.Log($"[P101XP] The AndroidManifest.xml file has been saved.\nPath: {targetPath}");
        }

        protected override string ReplaceParametersInText(string text)
        {
            // Base settings replacing.
            text = base.ReplaceParametersInText(text);

            // Facebook.
            // Read about: https://app.gitbook.com/@101xp/s/mobile-sdk/android/authorization/configure/facebook
            const string FACEBOOK_CONTENT_PROVIDER_AUTHORITIES_PREFIX = "com.facebook.app.FacebookContentProvider";
            text = text.Replace("{facebook_provider_app_id}", FACEBOOK_CONTENT_PROVIDER_AUTHORITIES_PREFIX + BaseSettings.FacebookAppId);
            text = text.Replace("{facebook_app_id}", BaseSettings.FacebookAppId);
            text = text.Replace("{facebook_invite_string}", BaseSettings.FacebookInviteString);
            text = text.Replace("{facebook_client_token}", BaseSettings.FacebookClientToken);
            text = text.Replace("{facebook_auth_enable}", androidSettings.FacebookAuthEnabled.ToString().ToLower());

            // Odnoklassniki.
            text = text.Replace("{ok_app_id}", androidSettings.OkAppId);
            text = text.Replace("{ok_app_key}", androidSettings.OkAppKey);
            text = text.Replace("{ok_redirect_url}", $"okauth://{androidSettings.OkAppId}");
            text = text.Replace("{ok_activity_host_app_id}", $"ok{androidSettings.OkAppId}");

            // Analytics.
            text = text.Replace("{analytics_project_id}", androidSettings.AnalyticsProjectId);
            text = text.Replace("{analytics_project_dev_id}", androidSettings.AnalyticsProjectId);
            text = text.Replace("{package_name}", androidSettings.PackageName);

            // Adjust
            text = text.Replace("{adjust_app_token}", androidSettings.AdjustAppToken);
            text = text.Replace("{adjust_event_map}", androidSettings.AdjustEventMap);
            text = text.Replace("{adjust_sand_box}", androidSettings.AdjustSandBox.ToString().ToLower());
            text = text.Replace("{adjust_log_level}", androidSettings.AdjustLogLevel.ToText());

            // Sentry
            text = text.Replace("{sentry_dsn}", androidSettings.SentryDSN);
            text = text.Replace("{sentry_environment}", androidSettings.SentryEnvironment);

            // Advertising
            text = text.Replace("{ad_admob_enabled}", androidSettings.AdAdmobEnabled.ToString().ToLower());
            text = text.Replace("{ad_iron_source_enabled}", androidSettings.AdIronSourceEnabled.ToString().ToLower());
            text = text.Replace("{ad_gms_ads_id}", androidSettings.AdGmsApplicationId);
            text = text.Replace("{ad_gms_appopen_ad_unit_id}", androidSettings.AdGmsAppopenAdUnitId);
            text = text.Replace("{ad_appopen_ad_time}", androidSettings.AdAppopenAdTime.ToString());
            text = text.Replace("{ad_appopen_ad_orientation}", androidSettings.AdAppopenAdOrientation.ToText());
            text = text.Replace("{ad_banner_ad_unit_id}", androidSettings.AdBannerAdUnitId);
            text = text.Replace("{ad_banner_ad_position_vertical}", androidSettings.AdBannerAdPositionVertical.ToText());
            text = text.Replace("{ad_banner_ad_position_horizontal}", androidSettings.AdBannerAdPositionHorizontal.ToText());
            text = text.Replace("{ad_banner_ad_size}", androidSettings.AdBannerAdSize.ToText());
            text = text.Replace("{ad_interstitial_ad_unit_id}", androidSettings.AdInterstitialAdUnitId);
            text = text.Replace("{ad_reward_ad_unit_id}", androidSettings.AdRewardAdUnitId);
            text = text.Replace("{ad_gms_rewardinterstitial_ad_unit_id}", androidSettings.AdGmsRewardinterstitialAdUnitId);
            text = text.Replace("{ad_tag_for_child_directed_treatment}", androidSettings.AdTagForChildDirectedTreatment.ToText());
            text = text.Replace("{ad_tag_for_under_age_of_consent}", androidSettings.AdTagForUnderAgeOfConsent.ToText());
            text = text.Replace("{ad_max_ad_content_rating}", androidSettings.AdMaxAdContentRating.ToText());
            text = text.Replace("{ad_admob_debug_geography}", androidSettings.AdAdmobDebugGeography.ToText());
            text = text.Replace("{ad_iron_source_app_key}", androidSettings.AdIronSourceAppKey);
            text = text.Replace("{ad_is_do_not_sell}", androidSettings.AdIsDoNotSell.ToString().ToLower());
            text = text.Replace("{ad_is_child_directed}", androidSettings.AdIsChildDirected.ToString().ToLower());
            text = text.Replace("{ad_test_device_ids_enabled}", androidSettings.AdTestDeviceIdsEnabled.ToString().ToLower());
            text = text.Replace("{ad_test_device_ids}", androidSettings.AdTestDeviceIds);

            // Other replaces.
            text = text.Replace("{app_skin_name}", androidSettings.AppSkinName);
            text = text.Replace("{fb_game_link}", androidSettings.FacebookGameLink);
            text = text.Replace("{fb_game_preview}", androidSettings.FacebookGamePreview);
            text = text.Replace("{gp_enabled}", androidSettings.GpEnabled.ToString().ToLower());
            text = text.Replace("{google_client_id}", androidSettings.GoogleClientId);
            text = text.Replace("{google_play_services_app_id}", androidSettings.GooglePlayServicesAppId);
            text = text.Replace("{google_auth_first_session}", androidSettings.GoogleAuthFirstSession.ToString().ToLower());
            text = text.Replace("{google_max_auto_authorize}", androidSettings.GoogleMaxAutoAuthorize.ToString());
            text = text.Replace("{billing_enabled}", androidSettings.BillingEnabled.ToString().ToLower());
            text = text.Replace("{billing_public_key}", androidSettings.BillingPublicKey);
            text = text.Replace("{billing_robokassa_enabled}", androidSettings.BillingRobokassaEnabled.ToString().ToLower());
            text = text.Replace("{notification_title}", androidSettings.NotificationTitle);
            text = text.Replace("{app_link}", androidSettings.AppLink);
            text = text.Replace("{dynamic_link_domain}", androidSettings.DynamicLinkDomain);
            text = text.Replace("{app_invite_message}", androidSettings.AppInviteMessage);
            text = text.Replace("{guest_enabled}", BaseSettings.GuestEnabled.ToString().ToLower());
            var skuStr = string.Empty;
            if (androidSettings.BillingSku != null)
            {
                skuStr = string.Join(",", androidSettings.BillingSku);
            }

            text = text.Replace("{billing_sku}", skuStr);
            return text;
        }
    }
}
