import Foundation
import UIKit
import AsyncDisplayKit

public final class PageControlNode: ASDisplayNode {
    private let dotSize: CGFloat
    private let dotSpacing: CGFloat
    public var dotColor: UIColor {
        didSet {
            if !oldValue.isEqual(self.dotColor) {
                let oldImage = self.normalDotImage
                self.normalDotImage = generateFilledCircleImage(diameter: dotSize, color: self.dotColor)!
                for dotNode in self.dotNodes {
                    if dotNode.image === oldImage {
                        dotNode.image = self.normalDotImage
                    }
                }
            }
        }
    }
    public var inactiveDotColor: UIColor {
        didSet {
            if !oldValue.isEqual(self.inactiveDotColor) {
                let oldImage = self.inactiveDotImage
                self.inactiveDotImage = generateFilledCircleImage(diameter: dotSize, color: self.inactiveDotColor)!
                for dotNode in self.dotNodes {
                    if dotNode.image === oldImage {
                        dotNode.image = self.inactiveDotImage
                    }
                }
            }
        }
    }
    private var dotNodes: [ASImageNode] = []
    
    private var normalDotImage: UIImage
    private var inactiveDotImage: UIImage

    public init(dotSize: CGFloat = 7.0, dotSpacing: CGFloat = 9.0, dotColor: UIColor, inactiveDotColor: UIColor) {
        self.dotSize = dotSize
        self.dotSpacing = dotSpacing
        self.dotColor = dotColor
        self.inactiveDotColor = inactiveDotColor
        self.normalDotImage = generateFilledCircleImage(diameter: dotSize, color: dotColor)!
        self.inactiveDotImage = generateFilledCircleImage(diameter: dotSize, color: inactiveDotColor)!
        
        super.init()
    }

    public var pagesCount: Int = 0 {
        didSet {
            if self.pagesCount != oldValue {
                while self.dotNodes.count > self.pagesCount {
                    self.dotNodes[self.dotNodes.count - 1].removeFromSupernode()
                    self.dotNodes.removeLast()
                }
                while self.dotNodes.count < self.pagesCount {
                    let dotNode = ASImageNode()
                    dotNode.image = self.normalDotImage
                    dotNode.displaysAsynchronously = false
                    dotNode.isUserInteractionEnabled = false
                    self.dotNodes.append(dotNode)
                    self.addSubnode(dotNode)
                }
            }
        }
    }
    
    public func setPage(_ pageValue: CGFloat) {
        let page = Int(round(pageValue))
        
        for i in 0 ..< self.dotNodes.count {
            if i != page {
                self.dotNodes[i].image = self.inactiveDotImage
            } else {
                self.dotNodes[i].image = self.normalDotImage
            }
        }
    }
    
    override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
        return CGSize(width: self.dotSize * CGFloat(self.pagesCount) + self.dotSpacing * max(CGFloat(self.pagesCount - 1), 0.0), height: self.dotSize)
    }
    
    override public func layout() {
        super.layout()
        
        let dotSize = CGSize(width: self.dotSize, height: self.dotSize)
        
        let nominalWidth = self.dotSize * CGFloat(self.pagesCount) + self.dotSpacing * max(CGFloat(self.pagesCount - 1), 0.0)

        let startX = floor((self.bounds.size.width - nominalWidth) / 2)
        
        for i in 0 ..< self.dotNodes.count {
            self.dotNodes[i].frame = CGRect(origin: CGPoint(x: startX + CGFloat(i) * (dotSize.width + self.dotSpacing), y: 0.0), size: dotSize)
        }
    }
}