//
//  TopNotification.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 9/11/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

import Foundation

open class TopNotificationModel: Codable {
    public var type: String
    public var priority = Operation.QueuePriority.normal
    public var molecule: MoleculeModelProtocol
    public var persistent = false
    public var dismissTime = 5
    public var pages: [String]?
    public var analyticsData: JSONValueDictionary?
    
    private enum CodingKeys: String, CodingKey {
        case type
        case priority
        case molecule
        case persistent
        case dismissTime
        case pages
        case analyticsData
    }
    
    //--------------------------------------------------
    // MARK: - Convenience Functions
    //--------------------------------------------------
    
    /// Set the priority using percent 0-100
    open func setPriority(with percent: Float) {
        // The new scale
        let scale = Operation.QueuePriority.veryHigh.rawValue - Operation.QueuePriority.veryLow.rawValue
        
        // Adjust the percent to the new scale
        let scaledPercent = (percent / 100.0) * Float(scale)
        
        // Finish shifting.
        priority = Operation.QueuePriority(rawValue: Operation.QueuePriority.veryLow.rawValue + Int(scaledPercent)) ?? .normal
    }
    
    /// Gets the priority as a percent (0-100)
    open func getPriorityPercent() -> Float {
        // Shift the value
        let shifted = Float(priority.rawValue - Operation.QueuePriority.veryLow.rawValue)
        
        // The current scale
        let scale = Operation.QueuePriority.veryHigh.rawValue - Operation.QueuePriority.veryLow.rawValue
        
        // Adjust to percent
        return (shifted / Float(scale)) * 100.0
    }
    
    open func createTopAlertObject() -> MVMCoreTopAlertObject {
        let object = MVMCoreTopAlertObject()
        object.persistent = persistent
        object.type = type
        object.topAlertDismissTime = dismissTime
        object.queuePriority = priority
        object.useNewStyle = true
        object.json = toJSON()
        return object
    }
    
    /// Decodes the top alert json to a model.
    public static func decode(json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) throws -> Self {
        let data = try JSONSerialization.data(withJSONObject: json)
        let decoder = JSONDecoder()
        if let delegateObject = delegateObject {
            try decoder.add(delegateObject: delegateObject)
        }
        return try decoder.decode(self, from: data)
    }
    
    //--------------------------------------------------
    // MARK: - Initializer
    //--------------------------------------------------
    
    public init(with type: String, molecule: MoleculeModelProtocol, priority: Operation.QueuePriority = .normal, persistent: Bool = false, dismissTime: Int = 5, pages: [String]? = nil, analyticsData: JSONValueDictionary? = nil) {
        self.type = type
        self.molecule = molecule
        self.priority = priority
        self.persistent = persistent
        self.dismissTime = dismissTime
        self.pages = pages
        self.analyticsData = analyticsData
    }
    
    //--------------------------------------------------
    // MARK: - Codec
    //--------------------------------------------------
    
    required public init(from decoder: Decoder) throws {
        let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
        type = try typeContainer.decode(String.self, forKey: .type)
        molecule = try typeContainer.decodeModel(codingKey: .molecule)
        if let priorityPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .priority) {
            setPriority(with: priorityPercent)
        }
        if let persistent = try typeContainer.decodeIfPresent(Bool.self, forKey: .persistent) {
            self.persistent = persistent
        }
        if let dismissTime = try typeContainer.decodeIfPresent(Int.self, forKey: .dismissTime) {
            self.dismissTime = dismissTime
        }
        pages = try typeContainer.decodeIfPresent([String].self, forKey: .pages)
        analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
    }
              
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(type, forKey: .type)
        try container.encodeModel(molecule, forKey: .molecule)
        try container.encode(getPriorityPercent(), forKey: .priority)
        try container.encode(persistent, forKey: .persistent)
        try container.encode(dismissTime, forKey: .dismissTime)
        try container.encodeIfPresent(pages, forKey: .pages)
        try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
    }
}
