//
//  KMTTSWindowController.swift
//  PDF Reader Pro
//
//  Created by liujiajie on 2023/12/12.
//

import Cocoa

typealias TTSCloseWindowCallback = (_ isCloseWindow: Bool) -> Void

let  minSpeed: Float = 0.6
let  maxSpeed: Float = 5.0
let  standardSpeed: Float = 175.0

class KMTTSWindowController: NSWindowController, KMTTSManagerDelegate, NSWindowDelegate, NSTextFieldDelegate{
    var pdfView: CPDFView!
    var closeWindowCallback: TTSCloseWindowCallback?
    @IBOutlet var sontinuouButton: NSButton!
    @IBOutlet var speedLabel: NSTextField!
    @IBOutlet var languageLabel: NSTextField!
    
    @IBOutlet var languageComboBox: NSPopUpButton!
    @IBOutlet var speedTextField: NSTextField!
    @IBOutlet var speedSlider: NSSlider!
    
    @IBOutlet var speedStepper: NSStepper!
    @IBOutlet var nextButton: NSButton!
    @IBOutlet var forwardButton: NSButton!
    
    @IBOutlet var playButton: NSButton!
    
    @IBOutlet var speedBox: NSBox!
    
    
    @IBOutlet var sppendCountLabel: NSTextField!
    
    
    var pdfSelection: CPDFSelection?
    
    var currentPageIndex: Int = 0
    
    var isChangePage = false
    
    var voiceArrays = NSMutableArray()
    
    static let share = KMTTSWindowController()
    
    convenience init() {
        self.init(windowNibName: "KMTTSWindowController")
    }
    deinit {
        DistributedNotificationCenter.default().removeObserver(self)
        NotificationCenter.default.removeObserver(self)
    }
    override func windowDidLoad() {
        super.windowDidLoad()
        self.window?.title = KMLocalizedString("TTS", comment: "")
        
        self.speedStepper.minValue = Double(minSpeed)
        self.speedStepper.maxValue = Double(maxSpeed);
        self.speedSlider.minValue = Double(minSpeed);
        self.speedSlider.maxValue = Double(maxSpeed);
        
        self.nextButton.toolTip = KMLocalizedString("Next Page")
//        self.nextButton.isShowCustomToolTip = true
        self.forwardButton.toolTip = KMLocalizedString("Previous Page")
         self.speedSlider.isEnabled = true
        self.speedStepper.isEnabled = true
        self.playButton.toolTip = KMLocalizedString("Play")
         self.sppendCountLabel.stringValue = KMLocalizedString("SpeedX")
        let str = String(format: "%.1f", KMTTSManager.defalutManager.rate/Float(standardSpeed))
        self.speedStepper.stringValue = str
        self.speedTextField.stringValue = str
        self.speedSlider.stringValue = str//[NSString stringWithFormat:@"%.1f",([KMTTSManager defaultManager].rate/standardSpeed)];
        
        self.sontinuouButton.title = KMLocalizedString("Continuous Reading");
        self.speedLabel.stringValue = KMLocalizedString("Speed") + ":"//[NSString stringWithFormat:@"%@:",KMLocalizedString("Speed", nil)];
        self.languageLabel.stringValue = KMLocalizedString("Language") + ":" //[NSString stringWithFormat:@"%@:",KMLocalizedString(@"Language", nil)];
        
        let array = KMTTSManager.defalutManager.availableVoices()
        let currentVoicName = KMTTSManager.defalutManager.voice()
        var currentIndex = 0
        let menu = NSMenu()
        
        for voiceType: NSSpeechSynthesizer.VoiceName in array {
            let voiceDic = NSMutableDictionary()
            //            let dic = KMTTSManager.defalutManager.attributesForVoice(voiceType)
            let voiceLocaleIdentifier = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.localeIdentifier ] as! String )
            
            let name = self.switchLanguage(withCode: voiceLocaleIdentifier)
            voiceDic["voiceType"] = voiceType
            voiceDic["voiceName"] = name
            voiceArrays.add(voiceDic)
        }
        voiceArrays = self.sortArray(voiceArrays)
        for i in 0..<voiceArrays.count {
            let voiceDic = voiceArrays[i] as! NSDictionary
            let voiceType = voiceDic.object(forKey: "voiceType") as! NSSpeechSynthesizer.VoiceName
            if currentVoicName == voiceType {
                currentIndex = i
            }
            
            let dic = KMTTSManager.defalutManager.attributesForVoice(voiceType) as NSDictionary
            let code = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.localeIdentifier ] as! String )
            var languageStaring: String? = nil
            let voiceName = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.name ] as! String )
            let name = self.switchLanguage(withCode: code)
            if voiceName.count > 0 {
                languageStaring = "\(name)(\(voiceName))"
            }
            
            let font = NSFont.systemFont(ofSize: 12.0)
            let namefont = NSFont.systemFont(ofSize: 10.0)
            
            let textRowSpace = NSMutableAttributedString(string: languageStaring ?? "")
            textRowSpace.addAttribute(.font, value: font, range: NSRange(location: 0, length: name.count))
            textRowSpace.addAttribute(.font, value: namefont, range: NSRange(location: name.count, length: languageStaring!.count - name.count))
            let item = NSMenuItem()
            item.attributedTitle = textRowSpace
            menu.addItem(item)
        }
        self.languageComboBox.menu = menu
        self.languageComboBox.selectItem(at: currentIndex)
        KMTTSManager.defalutManager.delegate = self
        self.updateViewColor()
        self.window?.standardWindowButton(.zoomButton)?.isHidden = true
        if KMTTSManager.defalutManager.isContinue {
            self.sontinuouButton.state = .on
        } else {
            self.sontinuouButton.state = .off
        }
        DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
       
        NotificationCenter.default.addObserver(self, selector: #selector(handlePageChangedNotification), name: NSNotification.Name.CPDFViewPageChanged, object: self.pdfView)
    }
    
    func updateViewColor() { 
        var viewBackcolor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)
        var textColor = NSColor(red: 51.0/255.0, green: 51.0/255.0, blue: 51.0/255.0, alpha: 1.0)
        var contentColor = NSColor(red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0)
        var fillColor = NSColor.white
        if #available(macOS 10.14, *) {
            let appearanceName = NSApp.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua])
            if appearanceName == .darkAqua {
                viewBackcolor = NSColor(red: 69.0/255.0, green: 69.0/255.0, blue: 71.0/255.0, alpha: 1.0)
                textColor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)
                contentColor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.6)
                fillColor = NSColor(red: 101.0/255.0, green: 101.0/255.0, blue: 101.0/255.0, alpha: 1.0)
            }
        }
        
        self.window?.backgroundColor = viewBackcolor
        self.window?.isMovableByWindowBackground = true
        self.languageLabel.textColor = contentColor
        self.speedLabel.textColor = contentColor
        self.speedTextField.textColor = textColor
        self.speedBox.fillColor = fillColor
        self.sontinuouButton.setTitleColor(contentColor)
    }
    
    
    @objc func themeChanged(notification: NSNotification) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.updateViewColor()
        }
    }
    @objc func handlePageChangedNotification(notification: NSNotification) {
        guard let PDFView = notification.object as? CPDFView else { return }
        if PDFView == self.pdfView {
            if self.pdfView.canGoToNextPage() {
                self.nextButton.isEnabled = true
            } else{
                self.nextButton.isEnabled = false
            }
            if self.pdfView.canGoToPreviousPage() {
                self.forwardButton.isEnabled = true
            } else {
                self.forwardButton.isEnabled = false
            }
        }
    }
    func sortArray(_ array: NSArray) -> NSMutableArray {
        let sortDesc = [NSSortDescriptor(key: "voiceName", ascending: true)]
        let sortedArr = array.sortedArray(using: sortDesc) as NSArray
        let tArray = NSMutableArray(array: sortedArr)
        return tArray
    }
    
    func windowShouldClose(_ sender: NSWindow) -> Bool {
        self.stopSpeaking()
        if let callBlack = closeWindowCallback {
            callBlack(true)
        }
        return true
    }
    
    override func showWindow(_ sender: Any?) {
        super.showWindow(sender)
        
        self.window?.center()
        
        self.isChangePage = false
        if self.pdfView.canGoToNextPage() {
            self.nextButton.isEnabled = true
        } else{
            self.nextButton.isEnabled = false
        }
        if self.pdfView.canGoToPreviousPage() {
            self.forwardButton.isEnabled = true
        } else {
            self.forwardButton.isEnabled = false
        }
    }
    
    func stopSpeaking() {
        if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
            self.isChangePage = true
            KMTTSManager.defalutManager.stopSpeaking()
            self.speedSlider.isEnabled = true
            self.speedStepper.isEnabled = true
            self.playButton.image = NSImage(named: "pause_fill")
            self.playButton.toolTip = KMLocalizedString("Play", comment: "")
            self.pdfView.setHighlightedSelections([])
        }
        self.pdfSelection = nil
        self.pdfView = nil
    }
    
    func quikeStartSpeakingPDFPage(_ page: CPDFPage) {
        if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
            KMTTSManager.defalutManager.stopSpeaking()
            self.isChangePage = true
        }
        self.currentPageIndex = Int(self.pdfView.document?.index(for: page) ?? 0)
        self.startSpeakingPDFPage(page)
    }
    func startSpeakingPDFPage(_ page: CPDFPage) {
        let dex = self.languageComboBox.indexOfSelectedItem
        if dex >= 0 && dex < self.voiceArrays.count {
            let dic: NSMutableDictionary = self.voiceArrays[dex] as! NSMutableDictionary
            if let voiceName = dic["voiceType"] {
                KMTTSManager.defalutManager.setVoice(voice: voiceName as! NSSpeechSynthesizer.VoiceName)
            }
        }
        KMTTSManager.defalutManager.rate = self.speedSlider.floatValue * Float(standardSpeed)
        let isSuccess = KMTTSManager.defalutManager.startSpeakingPDFPage(page)
        if isSuccess {
            self.playButton.image = NSImage(named: "play_fill")
            self.playButton.toolTip = KMLocalizedString("Pause", comment: "")
            self.speedSlider.isEnabled = false
            self.speedStepper.isEnabled = false
        } else {
            self.playButton.image = NSImage(named: "pause_fill")
            self.playButton.toolTip = KMLocalizedString("Play", comment: "")
            self.speedSlider.isEnabled = true
            self.speedStepper.isEnabled = true
        }
    }
    func startSpeakingPDFSelection(_ selection: CPDFSelection) {
        if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
            KMTTSManager.defalutManager.stopSpeaking()
            self.isChangePage = true
        }
        self.pdfSelection = selection
        self.pdfView?.setCurrentSelection(nil, animate: false)
        let dex = self.languageComboBox.indexOfSelectedItem
        if dex >= 0 && dex < self.voiceArrays.count {
            let dic: NSMutableDictionary = self.voiceArrays[dex] as! NSMutableDictionary
            if let voiceName = dic["voiceType"] as? NSSpeechSynthesizer.VoiceName {
                KMTTSManager.defalutManager.setVoice(voice: voiceName)
            }
        }
        KMTTSManager.defalutManager.rate = self.speedSlider.floatValue * Float(standardSpeed)
        let isSuccess = KMTTSManager.defalutManager.startSpeakingPDFSelection(selection)
        if isSuccess {
            self.speedSlider.isEnabled = false
            self.speedStepper.isEnabled = false
            self.playButton.image = NSImage(named: "play_fill")
            self.playButton.toolTip = KMLocalizedString("Pause", comment: "")
        } else {
            self.speedSlider.isEnabled = true
            self.speedStepper.isEnabled = true
            self.playButton.image = NSImage(named: "pause_fill")
            self.playButton.toolTip = KMLocalizedString("Play", comment: "")
        }
    }
    @IBAction func buttonItemClick_Next(_ sender: NSButton) {
        if (KMTTSManager.defalutManager.isSpeaking()) {
            let currentPageNum = self.currentPageIndex;
            var page: CPDFPage?
            if (currentPageNum + 1 < self.pdfView.document.pageCount) {
                page = self.pdfView.document.page(at: UInt(currentPageNum+1))
                self.currentPageIndex  = currentPageNum + 1;
                
            } else {
                page = self.pdfView.document.page(at: self.pdfView.document.pageCount - 1)
                self.currentPageIndex = Int(self.pdfView.document.pageCount - 1)
            }
            self.pdfView.go(to: page)
            self.isChangePage = true
            self.startSpeakingPDFPage(page!)
        }
    }
    @IBAction func buttonItemClick_Forward(_ sender: NSButton) {
        if (KMTTSManager.defalutManager.isSpeaking()) {
            let currentPageNum = self.currentPageIndex;
            var page: CPDFPage?
            if (currentPageNum - 1 < 0) {
                page = self.pdfView.document.page(at: 0)
                self.currentPageIndex  = 0;
                
            } else {
                page = self.pdfView.document.page(at: UInt(currentPageNum - 1))
                self.currentPageIndex = currentPageNum - 1
            }
            self.pdfView.go(to: page)
            self.isChangePage = true
            self.startSpeakingPDFPage(page!)
        }
    }
    @IBAction func buttonItemClick_Play(_ sender: NSButton) {
        if (KMTTSManager.defalutManager.isPaused) {
            self.playButton.image = NSImage(named: "play_fill")
            self.playButton.toolTip = KMLocalizedString("Pause")
            self.speedSlider.isEnabled = false
            self.speedStepper.isEnabled = false
            KMTTSManager.defalutManager.continueSpeaking()
        } else if (KMTTSManager.defalutManager.isSpeaking()) {
            self.isChangePage = true
            self.playButton.image = NSImage(named: "pause_fill")
            self.playButton.toolTip = KMLocalizedString("Play")

            self.speedSlider.isEnabled = true
            self.speedStepper.isEnabled = true
            self.pdfView.setHighlightedSelection(nil, animated: false)
            KMTTSManager.defalutManager.pauseSpeaking()
        } else {
            if ((self.pdfSelection) != nil) {
                self.startSpeakingPDFSelection(self.pdfSelection!)
            } else {
                let page = self.pdfView.currentPage()
                self.currentPageIndex = self.pdfView.currentPageIndex
                if page != nil {
                    self.startSpeakingPDFPage(page!)
                }
            }
        }
    }
    @IBAction func buttonItemClick_Continue(_ sender: NSButton) {
        KMTTSManager.defalutManager.isContinue = !(KMTTSManager.defalutManager.isContinue)
    }
    @IBAction func stepperItemClick_Speed(_ sender: NSButton) {
        var rate = self.speedStepper.floatValue
        let str = String(format: "%.1f", rate)
        self.speedStepper.stringValue = str
        self.speedTextField.stringValue = str
        self.speedSlider.stringValue = str
        rate = Float(standardSpeed) * rate
        KMTTSManager.defalutManager.rate = rate
    }
    @IBAction func sliderItemClick_Speed(_ sender: NSButton) {
        var rate: CGFloat = CGFloat(self.speedSlider.floatValue)
        let str = String(format: "%.1f", rate)
        self.speedStepper.stringValue = str
        self.speedTextField.stringValue = str
        self.speedSlider.stringValue = str
        rate = CGFloat(standardSpeed) * rate
        KMTTSManager.defalutManager.rate = Float(rate)
    }
    @IBAction func buttonItemClick_Language(_ sender: NSButton) {
        if KMTTSManager.defalutManager.isSpeaking() {
            self.isChangePage = true
            if let pdfSelection = self.pdfSelection {
                self.startSpeakingPDFSelection(pdfSelection)
            } else {
                let currentPageInd = self.currentPageIndex
                if currentPageInd < (self.pdfView.document.pageCount - 1) {
                    let page = self.pdfView.document.page(at: UInt(currentPageInd))
                    self.startSpeakingPDFPage(page!)
                }
            }
        }
    }
    override func mouseDown(with event: NSEvent) {
        super.mouseDown(with: event)
        self.window?.makeFirstResponder(self)
    }
    //MARK: KMTTSManagerDelegate
    func ttsMananger(_ tts: KMTTSManager, willSpeak selection: CPDFSelection) {
//        if (selection != nil) {
            self.pdfView?.setHighlightedSelection(selection, animated: false)
//        }
    }
    func ttsManangerDidFinishSpeech(_ tts: KMTTSManager) -> Bool {
        var isFinish = true
        if self.pdfSelection != nil {
            self.pdfSelection = nil
            self.pdfView.setHighlightedSelections(nil)
            self.playButton.image = NSImage(named: "pause_fill")
            self.speedSlider.isEnabled = true
            self.speedStepper.isEnabled = true
            self.playButton.toolTip = KMLocalizedString("Play")
        } else {
            if KMTTSManager.defalutManager.isContinue {
                if !isChangePage {
                    if let pdfSelection = self.pdfSelection {
                        self.pdfView.setHighlightedSelections(nil)
                        self.playButton.image = NSImage(named: "pause_fill")
                        self.speedSlider.isEnabled = true
                        self.speedStepper.isEnabled = true
                        self.playButton.toolTip = KMLocalizedString("Play")
                    } else {
                        let currentPageIndex = self.currentPageIndex
                        if currentPageIndex + 1 < self.pdfView.document.pageCount {
                            let page = self.pdfView.document.page(at: UInt(currentPageIndex+1))
                            self.currentPageIndex = currentPageIndex+1
                            self.pdfView.go(to: page)
                            self.startSpeakingPDFPage(page!)
                            isFinish = false
                        } else {
                            self.pdfView.setHighlightedSelections(nil)
                            self.playButton.image = NSImage(named: "pause_fill")
                            self.speedSlider.isEnabled = true
                            self.speedStepper.isEnabled = true
                            self.playButton.toolTip = KMLocalizedString("Play")
                        }
                    }
                }
            } else {
                if !isChangePage {
                    self.speedSlider.isEnabled = true
                    self.speedStepper.isEnabled = true
                    self.pdfView.setHighlightedSelections(nil)
                    self.playButton.image = NSImage(named: "pause_fill")
                    self.playButton.toolTip = KMLocalizedString("Play")
                }
            }
            if isChangePage {
                isChangePage = false
            }
        }
        return isFinish
    }
    func ttsManangerdidErrorSpeech(_ tts: KMTTSManager, message: String) {
        
    }
    //MARK: NSTextFieldDelegate
    func controlTextDidEndEditing(_ obj: Notification) {
        if let textField = obj.object as? NSTextField {
            if textField == self.speedTextField {
                var rate: Float = Float(textField.stringValue) ?? 0
                if maxSpeed - rate < 0 {
                    rate = maxSpeed
                } else if rate - minSpeed < 0 {
                    rate = minSpeed
                }
                self.speedStepper.stringValue = String(format: "%.1f", rate)
                self.speedTextField.stringValue = String(format: "%.1f", rate)
                self.speedSlider.stringValue = String(format: "%.1f", rate)
                rate = standardSpeed * rate
                KMTTSManager.defalutManager.rate = rate
            }
        }
    }
    
    func switchLanguage(withCode code: String) -> String {
        var language = code
        if code == "ar_SA" {
            language = "Arabic (Saudi Arabia)"
        } else if code == "cs_CZ" {
            language = "Czech (Czech republic)"
        } else if code == "da_DK" {
            language = "Danish (Denmark)"
        } else if code == "de_DE" {
            language = "German (Germany)"
        } else if code == "el_GR" {
            language = "Greek (Greece)"
        } else if code == "en_AU" {
            language = "English (Australia)"
        } else if code == "en_GB" {
            language = "English (UK)"
        } else if code == "en_IE" {
            language = "English (Ireland)"
        } else if code == "en_US" {
            language = "English"
        } else if code == "en_ZA" {
            language = "English (South Africa)"
        } else if code == "es_ES" {
            language = "Spanish (Spain)"
        } else if code == "es_MX" {
            language = "Spanish (Mexico)"
        } else if code == "fi_FI" {
            language = "Finnish (Finland)"
        } else if code == "fr_CA" {
            language = "French (Canada)"
        } else if code == "fr_FR" {
            language = "French (France)"
        } else if code == "he_IL" {
            language = "Hebrew"
        } else if code == "hi_IN" {
            language = "Hindi (India)"
        } else if code == "hu_HU" {
            language = "Hungarian (Hungary)"
        } else if code == "id_ID" {
            language = "Indonesian (Indonesia)"
        } else if code == "it_IT" {
            language = "Italian (Italy)"
        } else if code == "ja_JP" {
            language = "日本語"
        } else if code == "ko_KR" {
            language = "Korean (South Korea)"
        } else if code == "nl_BE" {
            language = "Dutch (Belgium)"
        } else if code == "nl_NL" {
            language = "Dutch (Holland)"
        } else if code == "nb_NO" {
            language = "Norwegian (Norway)"
        } else if code == "pl_PL" {
            language = "Polish (Poland)"
        } else if code == "pt_BR" {
            language = "Portuguese (Brazil)"
        } else if code == "pt_PT" {
            language = "Portuguese (Portugal)"
        } else if code == "ro_RO" {
            language = "Romanian (Romania)"
        } else if code == "ru_RU" {
            language = "Russian (Russia)"
        } else if code == "sk_SK" {
            language = "Slovakia (Slovakia)"
        } else if code == "sv_SE" {
            language = "Swe (Sweden)"
        } else if code == "th_TH" {
            language = "Thai (Thailand)"
        } else if code == "tr_TR" {
            language = "Turkish (Turkey)"
        } else if code == "zh_CN" {
            language = "简体中文"
        } else if code == "zh_HK" {
            language = "繁體中文 (香港)"
        } else if code == "zh_TW" {
            language = "繁體中文 (台灣)"
        } else if code == "en_IN" {
            language = "English"
        }
        return language
    }
}