//
//  TileContainerModel.swift
//  MVMCoreUI
//
//  Created by Matt Bruce on 4/15/24.
//  Copyright © 2024 Verizon Wireless. All rights reserved.
//

import Foundation
import VDS
import MVMCore

open class TileContainerModel: TileContainerBaseModel<TileContainer.Padding, TileContainer>, ParentMoleculeModelProtocol, MoleculeModelProtocol {
    
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    public static var identifier: String = "tileContainer"
    public var id: String = UUID().uuidString
    public var backgroundColor: Color?
    
    public var molecule: MoleculeModelProtocol?
    public var children: [any MoleculeModelProtocol] {
        guard let molecule else { return [] }
        return [molecule]
    }

    public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool  {
        return try replaceChildMolecule(at: &self.molecule, with: molecule)
    }

    private enum CodingKeys: String, CodingKey {
        case id
        case moleculeName
        case molecule
    }
    required public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
        molecule = try container.decodeMoleculeIfPresent(codingKey: .molecule)
        try super.init(from: decoder)
    }
    
    public override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(moleculeName, forKey: .moleculeName)
        try container.encodeModelIfPresent(molecule, forKey: .molecule)
        try super.encode(to: encoder)
    }
}


open class TileContainerBaseModel<PaddingType: DefaultValuing & Codable, TileContainerType:TileContainerBase<PaddingType>> : Codable{
    
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    public var inverted: Bool = false
    public var backgroundImage: String?
    public var action: ActionModelProtocol?
    public var imageFallbackColor: Surface = .light
    public var width: CGFloat?
    public var height: CGFloat?
    public var showBorder: Bool = false
    public var showDropShadow: Bool = false
    public var padding = PaddingType.defaultValue
    public var color: TileContainerType.BackgroundColor = .black
    public var aspectRatio: TileContainerType.AspectRatio = .ratio1x1
    public var backgroundEffect: TileContainerType.BackgroundEffect = .none
    public var surface: Surface { inverted ? .dark : .light }
    
    private enum CodingKeys: String, CodingKey {
        case inverted
        case backgroundImage
        case action
        case imageFallbackColor
        case width
        case height
        case showBorder
        case showDropShadow
        case padding
        case color
        case aspectRatio
        case backgroundEffect
    }
    required public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
        backgroundImage = try container.decodeIfPresent(String.self, forKey: .backgroundImage)
        action = try container.decodeModelIfPresent(codingKey: .action)
        imageFallbackColor = try container.decodeIfPresent(VDS.Surface.self, forKey: .imageFallbackColor) ?? .light
        width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
        height = try container.decodeIfPresent(CGFloat.self, forKey: .height)
        showBorder = try container.decodeIfPresent(Bool.self, forKey: .showBorder) ?? false
        showDropShadow = try container.decodeIfPresent(Bool.self, forKey: .showDropShadow) ?? false
        padding = try container.decodeIfPresent(PaddingType.self, forKey: .padding) ?? PaddingType.defaultValue
        color = try container.decodeIfPresent(TileContainerType.BackgroundColor.self, forKey: .color) ?? .black
        aspectRatio = try container.decodeIfPresent(TileContainerType.AspectRatio.self, forKey: .aspectRatio) ?? .ratio1x1
        backgroundEffect = try container.decodeIfPresent(TileContainerType.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none
        
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage)
        try container.encodeModelIfPresent(action, forKey: .action)
        try container.encodeIfPresent(imageFallbackColor, forKey: .imageFallbackColor)
        try container.encodeIfPresent(width, forKey: .width)
        try container.encodeIfPresent(height, forKey: .height)
        try container.encodeIfPresent(showBorder, forKey: .showBorder)
        try container.encodeIfPresent(showDropShadow, forKey: .showDropShadow)
        try container.encodeIfPresent(padding, forKey: .padding)
        try container.encodeIfPresent(color, forKey: .color)
        try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio)
        try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect)
    }
}
