//
//  CarouselModel.swift
//  MVMCoreUI
//
//  Created by Suresh, Kamlesh on 11/25/19.
//  Copyright © 2019 Verizon Wireless. All rights reserved.
//

import UIKit


@objcMembers public class CarouselModel: ParentMoleculeModelProtocol, FormFieldProtocol {
    
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    
    public static var identifier: String {
        return "carousel"
    }
    
    public var backgroundColor: Color?
    public var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]
    public var index: Int = 0
    public var spacing: CGFloat?
    public var border: Bool?
    public var loop: Bool?
    public var height: CGFloat?
    @Percent public var itemWidthPercent = 100
    public var itemAlignment: UICollectionView.ScrollPosition?
    public var pagingMolecule: (CarouselPagingModelProtocol & MoleculeModelProtocol)?
    public var paging: Bool = true
    public var useHorizontalMargins: Bool?
    public var leftPadding: CGFloat?
    public var rightPadding: CGFloat?
    public var accessibilityText: String?
    public var baseValue: AnyHashable?
    public var fieldKey: String?
    public var groupName: String = FormValidator.defaultGroupName
    public var enabled: Bool = true
    public var readOnly: Bool = false
    
    public var selectable = false
    public var selectedIndex: Int?
    
    public init(molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]) {
        self.molecules = molecules
    }
    
    public func formFieldValue() -> AnyHashable? {
        guard enabled else { return nil }
        
        guard selectable else {
            // Use visible item value, else index
            if let fieldValue = molecules[index].formFieldValue() {
                return fieldValue
            }
            return index
        }
        // Use selected item value, else index
        guard let selectedIndex = selectedIndex else { return nil }
        guard let fieldValue = molecules[selectedIndex].formFieldValue() else { return selectedIndex }
        return fieldValue
    }
    
    //--------------------------------------------------
    // MARK: - Keys
    //--------------------------------------------------
    
    private enum CodingKeys: String, CodingKey {
        case moleculeName
        case backgroundColor
        case molecules
        case index
        case spacing
        case border
        case loop
        case height
        case itemWidthPercent
        case itemAlignment
        case pagingMolecule
        case paging
        case useHorizontalMargins
        case leftPadding
        case rightPadding
        case accessibilityText
        case groupName
        case fieldKey
        case selectable
        case selectedIndex
        case enabled
        case readOnly
    }
    
    //--------------------------------------------------
    // MARK: - Codec
    //--------------------------------------------------
    
    required public init(from decoder: Decoder) throws {
        let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
        molecules = try typeContainer.decodeModels(codingKey: .molecules)
        index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0
        selectable = try typeContainer.decodeIfPresent(Bool.self, forKey: .selectable) ?? false
        selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex)
        backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
        spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
        border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
        loop = try typeContainer.decodeIfPresent(Bool.self, forKey: .loop)
        height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height)
        if let itemWidthPercent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .itemWidthPercent) {
            self.itemWidthPercent = itemWidthPercent
        }
        itemAlignment = try typeContainer.decodeIfPresent(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
        pagingMolecule = try typeContainer.decodeModelIfPresent(codingKey: .pagingMolecule)
        if let paging = try typeContainer.decodeIfPresent(Bool.self, forKey: .paging) {
            self.paging = paging
        }
        useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
        leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding)
        rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding)
        accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
        fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
        if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
            self.groupName = groupName
        }
        if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
            self.enabled = enabled
        }
        if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) {
            self.readOnly = readOnly
        }
        baseValue = formFieldValue()
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(moleculeName, forKey: .moleculeName)
        try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
        try container.encodeModels(molecules, forKey: .molecules)
        try container.encodeIfPresent(spacing, forKey: .spacing)
        try container.encodeIfPresent(border, forKey: .border)
        try container.encodeIfPresent(loop, forKey: .loop)
        try container.encodeIfPresent(height, forKey: .height)
        try container.encode(itemWidthPercent, forKey: .itemWidthPercent)
        try container.encodeIfPresent(itemAlignment, forKey: .itemAlignment)
        try container.encodeModelIfPresent(pagingMolecule, forKey: .pagingMolecule)
        try container.encode(paging, forKey: .paging)
        try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
        try container.encodeIfPresent(leftPadding, forKey: .leftPadding)
        try container.encodeIfPresent(rightPadding, forKey: .rightPadding)
        try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
        try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
        try container.encode(groupName, forKey: .groupName)
        try container.encode(index, forKey: .index)
        try container.encode(selectable, forKey: .selectable)
        try container.encode(selectedIndex, forKey: .selectedIndex)
        try container.encode(enabled, forKey: .enabled)
        try container.encode(readOnly, forKey: .readOnly)
    }
}

extension CarouselModel {
    
    public var children: [MoleculeModelProtocol] {
        return molecules
    }
    
}
