//
//  SunPhaseCell.swift
//  1Weather
//
//  Created by Dmitry Stepanets on 18.02.2021.
//

import UIKit

private struct CircleSegment {
    let chord:CGFloat
    let height:CGFloat
    var radius:CGFloat {
        return (height / 2) + (pow(chord,2) / (8 * height))
    }
    var diameter:CGFloat {
        return radius * 2
    }
    var alpha:CGFloat {
        return asin((radius - height) / radius)
    }
    
    init(chord:CGFloat, height:CGFloat) {
        self.chord = chord
        self.height = height
    }
}

class SunPhaseCell: UITableViewCell {
    //Private
    //Heading
    private let headingLabel = UILabel()
    private let arrowButton = ArrowButton()
    
    //Infographic
    private let infographicContainer = UIView()
    private let infographicLabel = UILabel()
    private let kDashLineTopInset:CGFloat = 14
    private let infographicDashLine = CAShapeLayer()
    private let earthImageView = UIImageView(image: UIImage(named: "earth"))
    
    //Sun
    private let sunImageView = UIImageView(image: UIImage(named: "sun"))
    private let sunActivityContainer = UIView()
    private let sunriseTimeLabel = UILabel()
    private let sunriseImageView = UIImageView(image: UIImage(named: "sun_up_arrow"))
    private let sunsetTimeLabel = UILabel()
    private let sunsetImageView = UIImageView(image: UIImage(named: "sun_down_arrow"))
    private let sunUvLineView = SunUvLineView()
    private let sunUvView = SunUvView()
    private let maxUvLabel = UILabel()
    private var sunProgress:CGFloat = 0.0
    
    //Computed
    private static let dateFormatter: DateFormatter = {
       let fmt = DateFormatter()
        fmt.dateFormat = "h:mm a"
        return fmt
    }()
    private static let nowDateFormatter:DateFormatter = {
        let fmt = DateFormatter()
        fmt.dateFormat = "yyyy-MM-dd h:mm a"
        return fmt
    }()
    private var earthCircleSegment:CircleSegment {
        return .init(chord: earthImageView.frame.width,
                     height: earthImageView.frame.height)
    }
    private var dashCircleSegment:CircleSegment {
        let kSideInset:CGFloat = 17
        let earthCircleSegment = self.earthCircleSegment
        return CircleSegment(chord: earthCircleSegment.chord + kSideInset * 2,
                             height: earthCircleSegment.height + kDashLineTopInset)
        
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        prepareCell()
        prepareHeading()
        prepareInfographicContainer()
        prepareSunActivityContainer()
        updateUI()
    }
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        updateUI()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        drawDashLine()
    }
    
    public func configure(with location:Location) {
        guard
            let sunrise = location.today?.sunrise,
            let sunset = location.today?.sunset
        else {
            return
        }
        
        SunPhaseCell.dateFormatter.timeZone = location.today?.timeZone
        SunPhaseCell.nowDateFormatter.timeZone = location.today?.timeZone
        sunriseTimeLabel.text = SunPhaseCell.dateFormatter.string(from: sunrise)
        sunsetTimeLabel.text = SunPhaseCell.dateFormatter.string(from: sunset)
        let sunTimePeriod = sunset.timeIntervalSince1970 - sunrise.timeIntervalSince1970
        let nowString = SunPhaseCell.nowDateFormatter.string(from: Date())
        let nowDate = SunPhaseCell.nowDateFormatter.date(from: nowString) ?? Date()
        
        //For pretty dash line view setting up min and max values
        let progress = CGFloat((nowDate.timeIntervalSince1970 - sunset.timeIntervalSince1970) / sunTimePeriod)
        var pathProgress = max(0.04, progress)
        pathProgress = min(0.96, pathProgress)
        self.sunProgress = pathProgress
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func drawDashLine() {
        infographicDashLine.path = dashLinePath(progress: 1.0).cgPath
    }
    
    private func dashLinePath(progress:CGFloat) -> UIBezierPath {
        let segment = dashCircleSegment
        let start = -(.pi - segment.alpha)
        let end = -segment.alpha
        let percent = (start - end) * progress
        let path = UIBezierPath(arcCenter: .init(x: earthImageView.center.x,
                                                 y: earthImageView.frame.origin.y + segment.radius - kDashLineTopInset),
                                radius: segment.radius,
                                startAngle: start,
                                endAngle: start - percent,
                                clockwise: true)
        return path
    }
    
    private func setUV(level:Int) {
        sunUvView.set(uvLevel: level)
        
        //Label
        let maxUvText = "sun.maxUV".localized()
        let levelText = "\(level)"
        let color = interfaceStyle == .light ? ThemeManager.currentTheme.secondaryTextColor :
                                                ThemeManager.currentTheme.primaryTextColor
        let attrStirng = NSMutableAttributedString(string: "\(maxUvText): \(level)",
                                                   attributes: [.foregroundColor : color,
                                                                .kern : 0.19,
                                                                .font : AppFont.SFPro.regular(size: 14)])
        attrStirng.addAttributes([.font : AppFont.SFPro.bold(size: 14)],
                                 range: NSRange(location: maxUvText.count + 2, length: levelText.count))
        maxUvLabel.attributedText = attrStirng
    }
    
    private func updateUI() {
        contentView.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
        
        switch interfaceStyle {
        case .light:
            infographicContainer.backgroundColor = UIColor(hex: 0xECEEF6)
            headingLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
            infographicLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
            infographicDashLine.strokeColor = UIColor(hex: 0x212334).cgColor
            sunriseTimeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
            sunriseImageView.tintColor = ThemeManager.currentTheme.secondaryTextColor
            sunsetTimeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
            sunsetImageView.tintColor = ThemeManager.currentTheme.secondaryTextColor
            sunActivityContainer.backgroundColor = .white
            sunActivityContainer.layer.shadowOpacity = 0.64
            sunActivityContainer.layer.borderWidth = 0
        case .dark:
            infographicContainer.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
            headingLabel.textColor = ThemeManager.currentTheme.primaryTextColor
            infographicLabel.textColor = ThemeManager.currentTheme.primaryTextColor
            infographicDashLine.strokeColor = UIColor(hex: 0xcae0ec).cgColor
            sunriseTimeLabel.textColor = ThemeManager.currentTheme.primaryTextColor
            sunriseImageView.tintColor = ThemeManager.currentTheme.primaryTextColor
            sunsetTimeLabel.textColor = ThemeManager.currentTheme.primaryTextColor
            sunsetImageView.tintColor = ThemeManager.currentTheme.primaryTextColor
            sunActivityContainer.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
            sunActivityContainer.layer.shadowOpacity = 0
            sunActivityContainer.layer.borderWidth = 1 / UIScreen.main.scale
        }
    }
    
    @objc private func handleArrowButton() {
        
    }
    
    //Public
    public func updateSunPosition() {
        contentView.layoutIfNeeded()
        
        sunImageView.layer.removeAnimation(forKey: "sun.position")
        sunImageView.frame.origin = .init(x: 20 - sunImageView.frame.width / 2,
                                          y: infographicContainer.frame.height - sunImageView.frame.height)
        
        let animation = CAKeyframeAnimation(keyPath: "position")
        animation.path = self.dashLinePath(progress: sunProgress).cgPath
        animation.calculationMode = .paced
        animation.duration = 1.3
        animation.rotationMode = .rotateAuto
        animation.isRemovedOnCompletion = false
        animation.fillMode = .forwards
        sunImageView.layer.add(animation, forKey: "sun.position")
    }
}

//MARK:- Prepare
private extension SunPhaseCell {
    func prepareCell() {
        selectionStyle = .none
    }
    
    func prepareHeading() {
        //Label
        headingLabel.font = AppFont.SFPro.bold(size: 16)
        headingLabel.text = "sun.title".localized().uppercased()
        contentView.addSubview(headingLabel)
        
        headingLabel.snp.makeConstraints { (make) in
            make.left.equalToSuperview().inset(18)
            make.top.equalToSuperview().inset(15)
        }
        
        //Arrow button
        arrowButton.addTarget(self, action: #selector(handleArrowButton), for: .touchUpInside)
        contentView.addSubview(arrowButton)
        
        arrowButton.snp.makeConstraints { (make) in
            make.width.height.equalTo(30)
            make.right.equalToSuperview().inset(18)
            make.centerY.equalTo(headingLabel)
        }
    }
    
    func prepareInfographicContainer() {
        //Container
        infographicContainer.layer.cornerRadius = 12
        contentView.addSubview(infographicContainer)
        
        infographicContainer.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview().inset(18)
            make.top.equalTo(headingLabel.snp.bottom).offset(18)
            make.height.equalTo(212)
        }
        
        //Label
        infographicLabel.lineBreakMode = .byWordWrapping
        infographicLabel.numberOfLines = 0
        infographicLabel.font = AppFont.SFPro.regular(size: 16)
        infographicLabel.text = "Reduce time in the sun between 10 a.m and 4 p.m"
        infographicContainer.addSubview(infographicLabel)
        
        infographicLabel.snp.makeConstraints { (make) in
            make.left.equalToSuperview().inset(18)
            make.top.equalToSuperview().inset(18)
            make.right.equalToSuperview().inset(18)
        }
        
        //Earth
        earthImageView.contentMode = .scaleAspectFit
        earthImageView.clipsToBounds = true
        infographicContainer.addSubview(earthImageView)
        
        earthImageView.snp.makeConstraints { (make) in
            make.centerX.equalToSuperview()
            make.bottom.equalToSuperview()
        }
        
        //Dash line
        infographicDashLine.fillColor = UIColor.clear.cgColor
        infographicDashLine.lineWidth = 1 / UIScreen.main.scale
        infographicDashLine.lineDashPattern = [4,2]
        infographicContainer.layer.addSublayer(infographicDashLine)
        
        //Sun
        sunImageView.frame = .init(origin: .zero, size: CGSize(width: 28, height: 28))
        sunImageView.contentMode = .scaleAspectFit
        infographicContainer.addSubview(sunImageView)
    }
    
    func prepareSunActivityContainer() {
        sunActivityContainer.clipsToBounds = false
        sunActivityContainer.layer.borderColor = UIColor(hex: 0x38383a).cgColor
        sunActivityContainer.layer.cornerRadius = 12
        sunActivityContainer.layer.shadowColor = UIColor(hex: 0xe5e6f4).cgColor
        sunActivityContainer.layer.shadowRadius = 18
        sunActivityContainer.layer.shadowOffset = .init(width: 5, height: 5)
        contentView.addSubview(sunActivityContainer)
        
        sunActivityContainer.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview().inset(18)
            make.top.equalTo(infographicContainer.snp.bottom).offset(10)
            make.bottom.equalToSuperview().inset(15)
        }
        
        //Start
        sunriseImageView.contentMode = .scaleAspectFit
        sunriseTimeLabel.font = AppFont.SFPro.regular(size: 14)
        sunriseTimeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
        sunriseTimeLabel.textAlignment = .left
        sunActivityContainer.addSubview(sunriseImageView)
        sunActivityContainer.addSubview(sunriseTimeLabel)
        
        sunriseImageView.snp.makeConstraints { (make) in
            make.left.top.equalToSuperview().inset(20)
        }
        sunriseTimeLabel.snp.makeConstraints { (make) in
            make.left.equalTo(sunriseImageView.snp.right).offset(3)
            make.centerY.equalTo(sunriseImageView)
        }
        
        //End
        sunsetImageView.contentMode = .scaleAspectFit
        sunsetTimeLabel.font = AppFont.SFPro.regular(size: 14)
        sunsetTimeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
        sunsetTimeLabel.textAlignment = .right
        sunActivityContainer.addSubview(sunsetImageView)
        sunActivityContainer.addSubview(sunsetTimeLabel)
        
        sunsetTimeLabel.snp.makeConstraints { (make) in
            make.right.equalToSuperview().inset(20)
            make.centerY.equalTo(sunriseTimeLabel)
        }
        sunsetImageView.snp.makeConstraints { (make) in
            make.right.equalTo(sunsetTimeLabel.snp.left).inset(-3)
            make.centerY.equalTo(sunriseImageView)
        }
        
        //UV levels
        sunUvView.set(uvLevel: 8)
        sunActivityContainer.addSubview(sunUvView)
        sunUvView.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview().inset(18)
            make.height.equalTo(8)
            make.top.equalTo(sunriseImageView.snp.bottom).offset(20)
        }
        
        //UL label
        setUV(level: 8)
        sunActivityContainer.addSubview(maxUvLabel)
        maxUvLabel.snp.makeConstraints { (make) in
            make.top.equalTo(sunUvView.snp.bottom).offset(11)
            make.centerX.equalToSuperview()
            make.bottom.bottom.equalToSuperview().inset(18)
        }
        
        //Separator
        sunActivityContainer.addSubview(sunUvLineView)
        sunUvLineView.snp.makeConstraints { (make) in
            make.left.equalTo(sunriseTimeLabel.snp.right).offset(8)
            make.right.equalTo(sunsetImageView.snp.left).offset(-8)
            make.height.equalTo(8)
            make.centerY.equalTo(sunriseTimeLabel)
        }
    }
}
