//
//  Label.swift
//  MVMCoreUI
//
//  Created by Suresh, Kamlesh on 10/3/19.
//  Copyright © 2019 Suresh, Kamlesh. All rights reserved.
//
import VDS 

@objcMembers open class LabelModel: MoleculeModelProtocol {
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    
    open class var identifier: String { "label" }
    public var id: String
    
    public var backgroundColor: Color?
    public var text: String
    public var accessibilityText: String?
    public var textColor: Color?
    public var fontStyle: Styler.Font?
    public var fontName: String?
    public var fontSize: CGFloat?
    public var textAlignment: NSTextAlignment?
    public var attributes: [LabelAttributeModel]?
    public var html: String?
    public var hero: Int?
    public var makeWholeViewClickable: Bool?
    public var numberOfLines: Int?
    public var shouldMaskRecordedView: Bool? = false
    public var accessibilityTraits: UIAccessibilityTraits?
    public var inverted: Bool = false
    
    //--------------------------------------------------
    // MARK: - Keys
    //--------------------------------------------------
    
    private enum CodingKeys: String, CodingKey {
        case id
        case moleculeName
        case text
        case accessibilityText
        case textColor
        case backgroundColor
        case fontStyle
        case fontName
        case fontSize
        case textAlignment
        case attributes
        case html
        case hero
        case inverted
        case makeWholeViewClickable
        case numberOfLines
        case shouldMaskRecordedView
        case accessibilityTraits
    }
    
    enum AttributeTypeKey: String, CodingKey {
        case type
    }
     
    //--------------------------------------------------
    // MARK: - Initializer
    //--------------------------------------------------
    
    public init(id: String = UUID().uuidString, text: String, textColor: Color? = nil) {
        self.id = id
        self.text = text
        self.textColor = textColor
    }
    
    //--------------------------------------------------
    // MARK: - Validations
    //--------------------------------------------------
    
    public func validate(_ attributes: [LabelAttributeModel]) throws {
        for attribute in attributes {
            try attribute.validateInRange(of: text)
        }
    }
    
    //--------------------------------------------------
    // MARK: - Codec
    //--------------------------------------------------
    
    required public init(from decoder: Decoder) throws {
        let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
        id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
        text = try typeContainer.decode(String.self, forKey: .text)
        accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
        textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)
        backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
        fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle)
        fontName = try typeContainer.decodeIfPresent(String.self, forKey: .fontName)
        fontSize = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .fontSize)
        textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment)
        attributes = try typeContainer.decodeModelsIfPresent(codingKey: .attributes)
        html = try typeContainer.decodeIfPresent(String.self, forKey: .html)
        hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero)
        inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
        makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable)
        numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines)
        shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? false
        accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits)
        
        // Later make protocol based validate outside of decoding?
        if let attributes = attributes {
            try validate(attributes)
        }
    }
    
    open func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
        try container.encode(id, forKey: .id)
        try container.encode(text, forKey: .text)
        try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
        try container.encodeIfPresent(textColor, forKey: .textColor)
        try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
        try container.encodeIfPresent(fontStyle, forKey: .fontStyle)
        try container.encodeIfPresent(fontName, forKey: .fontName)
        try container.encodeIfPresent(fontSize, forKey: .fontSize)
        try container.encodeIfPresent(textAlignment, forKey: .textAlignment)
        try container.encodeModelsIfPresent(attributes, forKey: .attributes)
        try container.encodeIfPresent(html, forKey: .html)
        try container.encodeIfPresent(hero, forKey: .hero)
        try container.encodeIfPresent(inverted, forKey: .inverted)
        try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable)
        try container.encodeIfPresent(numberOfLines, forKey: .numberOfLines)
        try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
        try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
    }
}

extension LabelModel {
    public var surface: Surface { inverted ? .dark : .light }
}
