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


import Foundation
import SpriteKit
import SPCCore
import SPCAudio


extension AudioPlaying where Self: InternalGraphic {
    func addAudio(_ sound: Sound, positional: Bool, looping: Bool, volume: Double) {
        _addAudio(sound, positional: positional, looping: looping, volume: volume)
    }
    
    func removeAudio() {
        _removeAudio()
    }
    
    func setIsAudioPositional(isAudioPositional: Bool) {
        _setIsPositionalAudio(isAudioPositional)
    }
    
    func playAudio() {
        _playAudio()
    }
    
    func stopAudio() {
        _stopAudio()
    }
}

public extension Collidable where Self: InternalGraphic {
    func setInteractionCategory(interactionCategory: InteractionCategory) {
        _interactionCategory = interactionCategory
    }
    
    func setCollisionCategories(collisionCategories: InteractionCategory) {
        _collisionCategories = collisionCategories
    }
    
    func setContactCategories(contactCategories: InteractionCategory) {
        _contactCategories = contactCategories
    }
    
    func setOnCollisionHandler(_ handler: @escaping (Collision)->Void) {
        _setOnCollisionHandler(handler)
    }
}

extension ImageProtocol where Self: InternalGraphic {
    func setImage(image: Image) {
        _setImage(image: image)
    }
    
    func setTiledImage(image: Image?, columns: Int?, rows: Int?, isDynamic: Bool?) {
        _setTiledImage(image: image, columns: columns, rows: rows, isDynamic: isDynamic)
    }
}

public extension TextProtocol where Self: InternalGraphic {
    var text: String {
        get {
            return _text ?? ""
        }
        set {
            _setText(newValue)
        }
    }
    
    var textColor: Color {
        get {
            return _textColor ?? UIColor.black
        }
        set {
            _setTextColor(newValue)
        }
    }
    
    var fontSize: Int {
        get {
            return _fontSize ?? 0
        }
        set {
            _setFontSize(newValue)
        }
    }
    
    var fontName: String {
        get {
            return _fontName ?? ""
        } set {
            _setFontName(newValue)
        }
    }
}

extension ShapeProtocol where Self: InternalGraphic {
    func setShape(_ shape: BasicShape?) {
        _setShape(shape)
    }
}

public extension Physicable where Self: InternalGraphic {
    func setAffectedByGravity(gravity: Bool) {
        _setAffectedByGravity(gravity: gravity)
    }
    
    func setIsDynamic(dynamic: Bool) {
        _setIsDynamic(dynamic: dynamic)
    }
    
    func setAllowsRotation(rotation: Bool) {
        _setAllowsRotation(rotation: rotation)
    }
    
    func setVelocity(velocity: CGVector) {
        _setVelocity(velocity: velocity)
    }
    
    func setRotationalVelocity(rotationalVelocity: Double) {
        _setRotationalVelocity(rotationalVelocity: rotationalVelocity)
    }
    
    func setBounciness(bounciness: Double) {
        _setBounciness(bounciness: bounciness)
    }
    
    func setFriction(friction: Double) {
        _setFriction(friction: friction)
    }
    
    func setDensity(density: Double) {
        _setDensity(density: density)
    }
    
    func setDrag(drag: Double) {
        _setDrag(drag: drag)
    }
    
    func setRotationalDrag(drag: Double) {
        _setRotationalDrag(drag: drag)
    }
    
    func applyImpulse(vector: CGVector) {
        _applyImpulse(vector: vector)
    }
    
    func applyForce(vector: CGVector, duration: Double) {
        _applyForce(vector: vector, duration: duration)
    }
}

extension Scaleable where Self: InternalGraphic {
    func setXScale(scale: Double) {
        
    }
    
    func setYScale(scale: Double) {
            
    }
}

public extension Emittable where Self: InternalGraphic {
    func addParticleEmitter(name: String, duration: Double, color: Color) {
        
    }
}

public extension Actionable where Self: InternalGraphic {
    func runAction(_ action: SKAction, name: String? = nil, completion: (()->Void)? = nil) {
        _runAction(action: action, name: name)
        
        if let comp = completion {
            comp()
        }
    }
    
    func removeAction(name: String) {
        _removeAction(name: name)
    }
    
    func removeAllActions() {
        _removeAllActions()
    }
    
    //TODO: turn SKActions into animatable functions with a duration parameter
    
    /// Pulsates the Graphic by increasing and decreasing its scale a given number of times, or indefinitely.
    ///
    /// - Parameter period: The period of each pulsation in seconds.
    /// - Parameter count: The number of pulsations; the default (`-1`) is to pulsate indefinitely.
    ///
    /// - localizationKey: Graphic.pulsate(period:count:)
    func pulsate(period: Double = 5.0, count: Int = -1) {
        _runAction(action: SKAction.pulsate(period: period, count: count), name: nil)
    }
    
    func scale(to scale: Double, duration: Double) {
        _runAction(action: SKAction.scale(to: CGFloat(scale), duration: TimeInterval(duration)), name: nil)
    }
    
    func fadeIn(after duration: Double) {
        _runAction(action: .fadeIn(withDuration: duration), name: "fadeIn")
    }
    
    func fadeOut(after duration: Double) {
        _runAction(action: .fadeOut(withDuration: duration), name: "fadeOut")
    }
}

extension TouchInteractable where Self: InternalGraphic {
    func setAllowsTouchInteraction(_ allowsTouchInteraction: Bool) {
        _setAllowsTouchInteraction(allowsTouchInteraction: allowsTouchInteraction)
    }
    
    func setHandler(for type: InteractionType, handler: @escaping () -> Void) {
        _setHandler(for: type, handler: handler)
    }
}
