//
//  AboutLicenseView.swift
//  CmdBar
//
//  Created by Igor Kolokolnikov on 8/16/23.
//

import AppKit

// MARK: - Constants
fileprivate enum AboutLinks {
    static let privacyLink = "https://cmdbar.app/#privacy-policy"
    static let purchaseLink = "https://cmdbar.app/purchase"
}

enum Strings {
    static let copyright = "Copyright © 2024 GarikMI. All rights reserved."
    static let evaluationTitle = "License - Evaluation"
    static let evaluationMessage = "You are currently using evaluation license. CmdBar will quit after 20 minutes. If you already own a license, enter it below or purchase a license."
    static let activate = "Activate"
    static let proTitle = "License - Activated"
    static let proMessage = "Thank you for purchasing CmdBar! Enjoy!"
    static let deactivate = "Deactivate"
    static let activating = "Activating..."
}

// MARK: - Controller
class AboutViewController: NSViewController, NSTextFieldDelegate {
    // MARK: - Views
    private var appIconImage: NSImageView = {
        //let image = NSImageView(image: NSApp.applicationIconImage)
        let image = NSImageView()
        image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
        image.imageScaling = .scaleAxesIndependently
        image.translatesAutoresizingMaskIntoConstraints = false
        return image
    }()

    private var appNameLabel: NSTextField = {
        let textField = NSTextField()
        textField.stringValue = (Bundle.main.infoDictionary?["CFBundleName"] as? String) ?? "NOT FOUND"
        textField.isEditable = false
        textField.isBezeled = false
        textField.drawsBackground = false
        textField.alignment = .left
        textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body).pointSize, weight: .bold)
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var versionLabel: NSTextField = {
        let textField = NSTextField()
        textField.stringValue = "Version \((Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "-.--")"
        textField.isEditable = false
        textField.isBezeled = false
        textField.drawsBackground = false
        textField.alignment = .left
        textField.textColor = NSColor.systemGray
        textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .subheadline).pointSize, weight: .regular)
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var copyrightLabel: NSTextField = {
        let textField = NSTextField()
        textField.stringValue = Strings.copyright
        textField.maximumNumberOfLines = 4
        textField.cell?.truncatesLastVisibleLine = true
        textField.isEditable = false
        textField.isBezeled = false
        textField.drawsBackground = false
        textField.alignment = .left
        textField.textColor = NSColor.systemGray
        textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .subheadline).pointSize, weight: .regular)
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var licenseLabel: NSTextField = {
        let textField = NSTextField()
        textField.stringValue = Strings.evaluationTitle
        textField.isEditable = false
        textField.isBezeled = false
        textField.drawsBackground = false
        textField.alignment = .left
        textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .title2).pointSize, weight: .bold)
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var licenseInfoLabel: NSTextField = {
        let textField = NSTextField()
        textField.stringValue = Strings.evaluationMessage
        textField.cell?.truncatesLastVisibleLine = true
        textField.maximumNumberOfLines = 6
        textField.isEditable = false
        textField.isBezeled = false
        textField.drawsBackground = false
        textField.alignment = .left
        textField.textColor = NSColor.systemGray
        textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .subheadline).pointSize, weight: .regular)
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var emailInput: EditableNSTextField = {
        let textField = EditableNSTextField()
        textField.placeholderString = "Email"
        textField.bezelStyle = .roundedBezel
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var licenseKeyInput: EditableNSTextField = {
        let textField = EditableNSTextField()
        textField.placeholderString = "License Key"
        textField.bezelStyle = .roundedBezel
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }()

    private var privacyButton: NSButton = {
        let button = NSButton()
        button.title = "Privacy Policy"
        button.sizeToFit()
        button.bezelStyle = .rounded
        button.action = #selector(privacy)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    private var closeButton: NSButton = {
        let button = NSButton()
        button.title = "Close"
        button.sizeToFit()
        button.bezelStyle = .rounded
        button.action = #selector(close)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    private var purchaseButton: NSButton = {
        let button = NSButton()
        button.title = "Purchase"
        button.sizeToFit()
        button.bezelStyle = .rounded
        button.action = #selector(purchase)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    private var activateButton: NSButton = {
        let button = NSButton()
        button.isEnabled = false
        button.title = "Activate"
        button.keyEquivalent = "\r"
        button.sizeToFit()
        button.bezelStyle = .rounded
        button.action = #selector(activate)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    private var dividerBox: NSBox = {
        let box = NSBox()
        box.boxType = .separator
        box.translatesAutoresizingMaskIntoConstraints = false
        return box
    }()

    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        // Input delegates
        emailInput.delegate = self
        licenseKeyInput.delegate = self

        // Program info
        view.addSubview(appIconImage)
        view.addSubview(appNameLabel)
        view.addSubview(versionLabel)
        view.addSubview(copyrightLabel)
        view.addSubview(privacyButton)

        // Divider
        view.addSubview(dividerBox)

        // License
        view.addSubview(licenseLabel)
        view.addSubview(licenseInfoLabel)
        view.addSubview(emailInput)
        view.addSubview(licenseKeyInput)

        // Action buttons
        view.addSubview(closeButton)
        view.addSubview(purchaseButton)
        view.addSubview(activateButton)

        setupConstraints()
    }

    override func viewDidAppear() {
        super.viewDidAppear()
        self.view.window?.center()
        checkLicense()
    }

    override func loadView() {
        self.view = NSView()
    }

    // MARK: - Constraints
    private func setupConstraints() {
        // View.
        NSLayoutConstraint.activate([
            view.widthAnchor.constraint(equalToConstant: 600),
            view.heightAnchor.constraint(lessThanOrEqualToConstant: 500),
        ])

        // App image.
        NSLayoutConstraint.activate([
            appIconImage.widthAnchor.constraint(equalToConstant: 60),
            appIconImage.heightAnchor.constraint(equalTo: appIconImage.widthAnchor, multiplier: 1),

            appIconImage.topAnchor.constraint(equalTo: view.topAnchor, constant: ViewConstants.spacing20),
            appIconImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: ViewConstants.spacing20),
        ])

        // Title
        NSLayoutConstraint.activate([
            appNameLabel.topAnchor.constraint(equalTo: appIconImage.topAnchor),
            appNameLabel.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing10),
            appNameLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),

            versionLabel.topAnchor.constraint(equalTo: appNameLabel.bottomAnchor, constant: ViewConstants.spacing2),
            versionLabel.leadingAnchor.constraint(equalTo: appNameLabel.leadingAnchor),
            versionLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),

            copyrightLabel.topAnchor.constraint(equalTo: versionLabel.bottomAnchor, constant: ViewConstants.spacing2),
            copyrightLabel.leadingAnchor.constraint(equalTo: appNameLabel.leadingAnchor),
            copyrightLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),

            privacyButton.topAnchor.constraint(equalTo: copyrightLabel.bottomAnchor, constant: ViewConstants.spacing10),
            privacyButton.leadingAnchor.constraint(equalTo: appNameLabel.leadingAnchor),
        ])

        NSLayoutConstraint.activate([
            dividerBox.topAnchor.constraint(equalTo: privacyButton.bottomAnchor, constant: ViewConstants.spacing10),
            dividerBox.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: ViewConstants.spacing20),
            dividerBox.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),
        ])

        // License labels.
        NSLayoutConstraint.activate([
            licenseLabel.topAnchor.constraint(equalTo: dividerBox.bottomAnchor, constant: ViewConstants.spacing10),
            licenseLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: ViewConstants.spacing20),
            licenseLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),

            licenseInfoLabel.topAnchor.constraint(equalTo: licenseLabel.bottomAnchor, constant: ViewConstants.spacing2),
            licenseInfoLabel.leadingAnchor.constraint(equalTo: licenseLabel.leadingAnchor),
            licenseInfoLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),
        ])

        // License inputs.
        NSLayoutConstraint.activate([
            emailInput.topAnchor.constraint(equalTo: licenseInfoLabel.bottomAnchor, constant: ViewConstants.spacing10),
            emailInput.leadingAnchor.constraint(equalTo: licenseInfoLabel.leadingAnchor),
            emailInput.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),

            licenseKeyInput.topAnchor.constraint(equalTo: emailInput.bottomAnchor, constant: ViewConstants.spacing10),
            licenseKeyInput.leadingAnchor.constraint(equalTo: licenseInfoLabel.leadingAnchor),
            licenseKeyInput.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),
        ])

        // License buttons.
        NSLayoutConstraint.activate([
            activateButton.topAnchor.constraint(equalTo: licenseKeyInput.bottomAnchor, constant: ViewConstants.spacing20),
            activateButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing20),
            activateButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -ViewConstants.spacing20),

            purchaseButton.trailingAnchor.constraint(equalTo: activateButton.leadingAnchor, constant: -ViewConstants.spacing10),
            purchaseButton.lastBaselineAnchor.constraint(equalTo: activateButton.lastBaselineAnchor),

            closeButton.trailingAnchor.constraint(equalTo: purchaseButton.leadingAnchor, constant: -ViewConstants.spacing10),
            closeButton.lastBaselineAnchor.constraint(equalTo:  purchaseButton.lastBaselineAnchor),
        ])
    }

    // MARK: - Button Functions
    @objc private func privacy() {
        NSWorkspace.shared.open(URL(string: AboutLinks.privacyLink)!)
    }

    @objc private func close() {
        view.window?.orderOut(nil)
    }

    @objc private func purchase() {
        guard let url = URL(string: AboutLinks.purchaseLink) else { return }
        NSWorkspace.shared.open(url)
    }

    @objc private func activate() {
        let email = emailInput.stringValue
        let key = licenseKeyInput.stringValue
        if email.isEmpty || key.isEmpty { return }
        
        activateButton.isEnabled = false
        activateButton.title = Strings.activating

        // TODO: Notify the user if registration failed.
        LicenseManager.standard.activateLicense(email: email, key: key) { [weak self] _ in
            DispatchQueue.main.async { self?.checkLicense() }
        }
    }
    
    @objc private func deactivate() {
        LicenseManager.standard.deactivateLicense()
        checkLicense()
    }

    private func checkLicense() {
        if LicenseManager.standard.isRegistered() {
            activateButton.isEnabled = true
            activateButton.title = Strings.deactivate
            activateButton.action = #selector(deactivate)

            licenseLabel.stringValue = Strings.proTitle
            licenseInfoLabel.stringValue = Strings.proMessage

            emailInput.isEnabled = false
            licenseKeyInput.isEnabled = false

            let license = LicenseManager.standard.getLicense()
            emailInput.stringValue = license.email
            licenseKeyInput.stringValue =
                "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXX" +
                license.key.dropFirst(license.key.count - 5)
        } else {
            activateButton.isEnabled = false
            activateButton.title = Strings.activate
            activateButton.action = #selector(activate)

            licenseLabel.stringValue = Strings.evaluationTitle
            licenseInfoLabel.stringValue = Strings.evaluationMessage

            emailInput.isEnabled = true
            licenseKeyInput.isEnabled = true

            emailInput.stringValue = ""
            licenseKeyInput.stringValue = ""
            
            emailInput.becomeFirstResponder()
        }

#if(DEBUG)
        emailInput.stringValue = "igorkolokolnikov@icloud.com"
        licenseKeyInput.stringValue = "137A5010-A95A-4A8C-A037-6DF16B6CA666"
#endif
    }
}

extension AboutViewController {
    func controlTextDidChange(_ obj: Notification) {
        activateButton.isEnabled = !(emailInput.stringValue.isEmpty || licenseKeyInput.stringValue.isEmpty)
    }
}
