﻿using System;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;

namespace BugseePlugin
{
    /// <summary>
    /// Contains options that help you configure the behavior of Bugsee.
    /// </summary>
    public class IOSLaunchOptions : BugseeLaunchOptions
    {
        public IOSLaunchOptions()
        {
            this.SetDefaults();
        }

        private void SetDefaults()
        {
            MaxRecordingTime = 60;
            ShakeToReport = false;
            ScreenshotToReport = true;
            CrashReport = true;
            KillDetection = false;
            VideoEnabled = true;
            MaxNetworkBodySize = 20 * 1024;
            VideoScale = 0.0f;
            CaptureLogs = true;
            MonitorNetwork = true;
            ReportPrioritySelector = false;
            FrameRate = BugseeFrameRate.High;
            DefaultCrashPriority = BugseeSeverityLevel.Blocker;
            DefaultBugPriority = BugseeSeverityLevel.Low;
            Style = BugseeStyle.Default;
            WifiOnlyUpload = false;
            MaxDataSize = 50;
            CaptureDeviceAndNetworkNames = false;
            ReportLabelsRequired = false;
            ReportDescriptionRequired = false;
            ReportEmailRequired = false;
            ReportSummaryRequired = false;
            ReportLabelsEnabled = false;
            DetectAppExit = false;
            ViewHierarchyEnabled = false;
            CaptureOSLogs = false;
            MonitorBluetoothStatus = false;
            MonitorDiskSpace = false;
            AppLaunchCrashDetection = false;
            CaptureAVPlayer = false;
        }

        public override void Reset()
        {
            base.Reset();
            this.SetDefaults();
        }

        public static BugseeLaunchOptions GetDefaultOptions()
        {
            return new IOSLaunchOptions();
        }

        /// <summary>
        /// Maximum size of network body that is allowed to be captured.
        /// </summary>
        /// <value>The max network body size.</value>
        public int MaxNetworkBodySize
        {
            get { return (int)this["bodySizeLimit"]; }
            set { this["bodySizeLimit"] = value; }
        }

        /// <summary>
        /// Additional down scaling applied to recorded video, (e.g., 0.5 would reduce both width and height by half).
        /// </summary>
        /// <value>Default: 0 - means not used</value>
        public float VideoScale
        {
            get { return (float)this["VideoScale"]; }
            set { this["VideoScale"] = value; }
        }

		/// <summary>
		/// Use this option to change frame rate to Low, Medium or High
		/// </summary>
		/// <value>Framerate value.</value>
		public BugseeFrameRate FrameRate
		{
            get { return (BugseeFrameRate)this["FrameRate"]; }
			set { this["FrameRate"] = value; }
		}

        /// <summary>
        /// Maximum recording duration
        /// </summary>
        /// <value>The max recording time.</value>
        public int MaxRecordingTime
        {
            get { return (int)this["MaxRecordingTime"]; }
            set { this["MaxRecordingTime"] = value; }
        }

        /// <summary>
        /// Bugsee will avoid using more disk space than specified. <br/>
        /// Option has value of int type and should be specified in Mb.Value should not be smaller than 10.
        /// </summary>
        /// <value>The max data size. Default: 50</value>
        public int MaxDataSize
        {
            get { return (int)this["MaxDataSize"]; }
            set { this["MaxDataSize"] = value; }
        }

        /// <summary>
        /// Shake gesture to trigger report
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool ShakeToReport
        {
            get { return (bool)this["ShakeToReport"]; }
            set { this["ShakeToReport"] = value; }
        }

        /// <summary>
        /// Screenshot key to trigger report
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool ScreenshotToReport
        {
            get { return (bool)this["ScreenshotToReport"]; }
            set { this["ScreenshotToReport"] = value; }
        }

        /// <summary>
        /// Catch and report application crashes
        /// </summary>
        /// <value><c>true</c> if crash report; otherwise, <c>false</c>.</value>
        /// <remarks>
        /// iOS allows only one crash detector to be active at a time, if you insist
        /// on using an alternative solution for handling crashes, you might want to
        /// use this option and disable Bugsee from taking over.
        /// </remarks>
        public bool CrashReport
        {
            get { return (bool)this["CrashReport"]; }
            set { this["CrashReport"] = value; }
        }

        /// <summary>
        /// Detect abnormal termination (experimental)
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool KillDetection
        {
            get { return (bool)this["BugseeKillDetectionKey"]; }
            set { this["BugseeKillDetectionKey"] = value; }
        }

        /// <summary>
        /// Controls whether early crashes are intercepted and uploaded.
        /// Early crashes are those happening within first 5 seconds
        /// after app launch. And they are uploaded synchronously
        /// (with blocking main thread) to guarantee upload
        /// </summary>
        public bool AppLaunchCrashDetection
        {
            get { return (bool)this["BugseeAppLaunchCrashDetectionKey"]; }
            set { this["BugseeAppLaunchCrashDetectionKey"] = value; }
        }

        /// <summary>
        /// Detect any kind of process termination (e.g. when user swipes
        /// off the application from multitasking UI, or when system unloads
        /// the app due memory pressure). Special error report is generated
        /// for this scenario with "BugseeAppExit" domain
        /// </summary>
        public bool DetectAppExit
        {
            get { return (bool)this["DetectAppExit"]; }
            set { this["DetectAppExit"] = value; }
        }

        /// <summary>
        /// Enable video recording
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool VideoEnabled
        {
            get { return (bool)this["VideoEnabled"]; }
            set { this["VideoEnabled"] = value; }
        }

        /// <summary>
        /// Flag that controls view hierarchy capturing for Bug reports. If
        /// true, Bugsee will capture view hierarchy and attach it to the
        /// report. If false, view hierarchy will not be captured.
        /// </summary>
        public bool ViewHierarchyEnabled
        {
            get { return (bool)this["ViewHierarchyEnabled"]; }
            set { this["ViewHierarchyEnabled"] = (bool)value; }
        }

        /// <summary>
        /// When enabled, video playing via AVPlayerLayer and via
        /// AVPlayerViewController will be captured on video
        /// </summary>
        public bool CaptureAVPlayer
        {
            get { return (bool)this["CaptureAVPlayer"]; }
            set { this["CaptureAVPlayer"] = (bool)value; }
        }

        /// <summary>
        /// Automatically capture all console logs
        /// </summary>
        /// <value><c>true</c> ito enable; otherwise, <c>false</c>.</value>
        public bool CaptureLogs
        {
            get { return (bool)this["CaptureLogs"]; }
            set { this["CaptureLogs"] = value; }
        }

        /// <summary>
        /// Automatically capture OSLog and Logger print statements. Not
        /// this that this may incur a slight performance penalty.
        /// </summary>
        public bool CaptureOSLogs
        {
            get { return (bool)this["CaptureOSLogs"]; }
            set { this["CaptureOSLogs"] = value; }
        }

        /// <summary>
        /// Capture network traffic
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool MonitorNetwork
        {
            get { return (bool)this["MonitorNetwork"]; }
            set { this["MonitorNetwork"] = value; }
        }

        /// <summary>
        /// Monitor bluetooth state.
        ///
        /// IMPORTANT: You must add "Privacy - Bluetooth Always Usage Description"
        /// key into your Info.plist with a string value explaining to the user
        /// why you need bluetooth permission
        /// </summary>
        public bool MonitorBluetoothStatus
        {
            get { return (bool)this["MonitorBluetoothStatus"]; }
            set { this["MonitorBluetoothStatus"] = value; }
        }

        /// <summary>
        /// Monitor disk space changes.
        /// </summary>
        public bool MonitorDiskSpace
        {
            get { return (bool)this["MonitorDiskSpace"]; }
            set { this["MonitorDiskSpace"] = value; }
        }

        /// <summary>
        /// Bugsee upload allowed only by wifi
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool WifiOnlyUpload
        {
            get { return (bool)this["WifiOnlyUpload"]; }
            set { this["WifiOnlyUpload"] = value; }
        }

        /// <summary>
        /// Screenshot that appears in report
        /// Default: When videoEnabled it's true, but if videoEnabled == false it's false
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool ScreenshotEnabled
        {
            get { return (bool)this["ScreenshotEnabled"]; }
            set { this["ScreenshotEnabled"] = value; }
        }


        /// <summary>
        /// Allow user to modify priority when reporting manually
        /// </summary>
        /// <value><c>true</c> to enable; otherwise, <c>false</c>.</value>
        public bool ReportPrioritySelector
        {
            get { return (bool)this["BugseeReportPrioritySelector"]; }
            set { this["BugseeReportPrioritySelector"] = value; }
        }

        /// <summary>
        /// Default priority for crashes
        /// </summary>
        /// <value>The default crash priority.</value>
        public BugseeSeverityLevel DefaultCrashPriority
        {
            get { return (BugseeSeverityLevel)this["BugseeDefaultCrashPriority"]; }
            set { this["BugseeDefaultCrashPriority"] = value; }
        }

        /// <summary>
        /// Default priority for bugs
        /// </summary>
        /// <value>The default bug priority.</value>
        public BugseeSeverityLevel DefaultBugPriority
        {
            get { return (BugseeSeverityLevel)this["BugseeDefaultBugPriority"]; }
            set { this["BugseeDefaultBugPriority"] = value; }
        }

        /// <summary>
        /// Defines the style which is used in Bugsee reporting UI
        /// </summary>
        /// <value>The style.</value>
        public BugseeStyle Style
        {
            get
            {
                var styleObj = this["BugseeStyle"];

                if (styleObj != null)
                {
                    return (BugseeStyle)Enum.Parse(typeof(BugseeStyle), styleObj.ToString());
                }

                return BugseeStyle.Default;
            }
            set
            {
                this["BugseeStyle"] = Enum.GetName(typeof(BugseeStyle), value);
            }
        }

        public bool CaptureDeviceAndNetworkNames
        {
            get { return (bool)this["CaptureDeviceAndNetworkNames"]; }
            set { this["CaptureDeviceAndNetworkNames"] = value; }
        }

        /// <summary>
        /// Controls whether the labels input field is
        /// mandatory in the built-in bug reporting UI.
        /// </summary>
        public bool ReportLabelsRequired
        {
            get { return (bool)this["ReportLabelsRequired"]; }
            set { this["ReportLabelsRequired"] = (bool)value; }
        }

        /// <summary>
        /// Controls whether the description input field is
        /// mandatory in the built-in bug reporting UI.
        /// </summary>
        public bool ReportDescriptionRequired
        {
            get { return (bool)this["ReportDescriptionRequired"]; }
            set { this["ReportDescriptionRequired"] = (bool)value; }
        }


        /// <summary>
        /// Controls whether the email input field is
        /// mandatory in the built-in bug reporting UI.
        /// </summary>
        public bool ReportEmailRequired
        {
            get { return (bool)this["ReportEmailRequired"]; }
            set { this["ReportEmailRequired"] = (bool)value; }
        }


        /// <summary>
        /// Controls whether the summary input field is
        /// mandatory in the built-in bug reporting UI.
        /// </summary>
        public bool ReportSummaryRequired
        {
            get { return (bool)this["ReportSummaryRequired"]; }
            set { this["ReportSummaryRequired"] = (bool)value; }
        }

        /// <summary>
        /// Controls whether the labels input field is
        /// enabled in the built-in bug reporting UI.
        /// </summary>
        public bool ReportLabelsEnabled
        {
            get { return (bool)this["ReportLabelsEnabled"]; }
            set { this["ReportLabelsEnabled"] = (bool)value; }
        }
    }
}
