//
//  Graphic.swift
//
//  Copyright © 2020 Apple Inc. All rights reserved.
//


import Foundation
import CoreGraphics
import SPCCore

open class Graphic: BaseGraphic, AudioPlaying, ImageProtocol, TextProtocol, ShapeProtocol, Scaleable, Actionable, Emittable {
    
    fileprivate static var defaultNameCount = 1
    
    public init(graphicType: GraphicType = .graphic, name: String = "") {
        super.init()
        self.graphicType = graphicType
        self.name = name
        //SceneProxy().createNode(id: id, graphicName: name, graphicType: graphicType)
    }
    
    /// Creates a Graphic with the given identifier; for example, reconstructing a graphic.
    ///
    /// - Parameter id: The identifier associated with the Graphic.
    /// - Parameter graphicType: The graphic type associated with the Graphic.
    /// - Parameter name: The name associated with the Graphic.
    ///
    /// - localizationKey: Graphic(id:name:graphicType:)
    public init(id: String, graphicType: GraphicType = .graphic, name: String = "") {
        super.init()
        self.name = name
        self.graphicType = graphicType
    }
    
        
    /// Creates a Graphic from a given image and name.
    ///
    /// - Parameter image: The image you choose to create the Graphic.
    /// - Parameter name: The name you give to the Graphic.
    ///
    /// - localizationKey: Graphic(image:name:)
    public init(image: Image, name: String = "") {
        super.init()
        self.graphicType = graphicType
        if name == "" {
            self.name = "graphic" + String(Graphic.defaultNameCount)
            Graphic.defaultNameCount += 1
        } else {
            self.name = name
        }
        
        self.image = image
        
        updateSize()
        
        /*
            Manually sending a message here, as setting a property on a struct
            from within one of its own initializers won’t trigger the didSet property.
        */
        //SceneProxy().setImage(id: id, image: image)
    }
    
    /// Creates a Graphic with a specified shape, color, gradient, and name.
    /// Example usage:
    /// ````
    /// let pentagon = Graphic(shape: .polygon(radius: 50, sides: 5), color: .red, gradientColor: .yellow, name: \"pentagon\")
    /// ````
    /// - Parameter shape: One of the Graphic shapes.
    /// - Parameter color: A fill color for the Graphic.
    /// - Parameter gradientColor: A secondary color for the gradient.
    /// - Parameter name: An optional name you can give to the shape. You can choose to leave the name blank.
    ///
    /// - localizationKey: Graphic(shape:color:gradientColor:name:)
    public convenience init(shape: Shape, color: Color, gradientColor: Color? = nil, name: String = "") {
        if name == "" {
            self.init(graphicType: .graphic, name: "graphic" + String(Graphic.defaultNameCount))
            Graphic.defaultNameCount += 1
        } else {
            self.init(graphicType: .graphic, name: name)
        }
        
        updateShape(shape: shape, color: color, gradientColor: gradientColor ?? color)
        
        updateSize()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func updateShape(shape: Shape, color: Color, gradientColor: Color) {
        let basicShape: BasicShape
        switch shape {
        case .circle(let radius):
            basicShape = .circle(radius: radius, color: color, gradientColor: gradientColor)
        case .rectangle(let width, let height, let cornerRadius):
            basicShape = .rectangle(width: width, height: height, cornerRadius: cornerRadius, color: color, gradientColor: gradientColor)
        case .polygon(let radius, let sides):
            basicShape = .polygon(radius: radius, sides: sides, color: color, gradientColor: gradientColor)
        case .star(let radius, let points, let sharpness):
            basicShape = .star(radius: radius, points: points, sharpness: sharpness, color: color, gradientColor: gradientColor)
        }
        
        self.shape = basicShape
        /*
         Manually sending a message here, as setting a property on a struct
         from within one of its own initializers won’t trigger the didSet property.
         */
        //SceneProxy().setShape(id: id, shape: basicShape)
    }
}
