//
//  FirstViewController.swift
//  eMojiCalc
//
//  Created by Taiji Yamada on 2019/09/05.
//  Copyright © 2019 Taiji Yamada. All rights reserved.
//

import UIKit

class FirstViewController: UIViewController {
    
    let specialUnicodeScalarValues: [ String: UInt32 ] = [
        "|": 0x200D,	// ZWJ: Zero Width Joiner
        "≆": 0xFE0E,    // VARIATION SELECTOR-15 (TPVS)
        "≇": 0xFE0F,    // VARIATION SELECTOR-16 (EPVS)
    ]
    let unicodeScalarValueRangeOfNormalAZ = "A".unicodeScalars.first!.value ... "Z".unicodeScalars.first!.value // 通常大文字アルファベット
    let unicodeScalarValueRangeOfSpecialAZ = "🇦".unicodeScalars.first!.value ... "🇿".unicodeScalars.first!.value // 特殊大文字アルファベット
    let unicodeScalarValueRangeOfAlternateAZ = "🄰".unicodeScalars.first!.value ... "🅉".unicodeScalars.first!.value // 代用大文字アルファベット
    let unicodeScalarValueRangeOfEMF = "🏻".unicodeScalars.first!.value ... "🏿".unicodeScalars.first!.value // Fitzpatrickスケール - スキンカラー

    @IBOutlet weak var scalarLabel: UILabel! // 合成前の文字列
    @IBOutlet weak var nativeLabel: UILabel! // 合成後の文字列
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        scalarLabel.text?.removeAll()
        nativeLabel.text?.removeAll()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        self.view.endEditing(true)
    } // キーボードを閉じるための override
    
    @IBAction func normalButtonTouchUpInside(_ sender: UIButton) {
        if sender.currentTitle == "˅" { // ここはまだ未実装なのでアラートして、何もせず、return
            let titles = [
                ( "Preparering", """
                    The function of this button is “Preparing”.
                    
                    There are many other emoji. We are considering making it easy to select them, so please enjoy the prepared emoji and “the combination”.
                    """
                    , "OK only"
                ),
                ( "準備中", """
                    このボタンの機能は「準備中」です。
                    
                    他にもたくさんの絵文字があります。それらを選びやすいように検討してますので、あり合わせの絵文字と「その組み合わせ」を楽しんで下さい。
                    """
                    , "OKのみ"
                )
            ]
            let i = Locale.current.identifier.dropLast(3) == "ja" || Locale.current.identifier.dropFirst(3) == "JP" ? 1 : 0 // 英日ロケールの選択のための添え字
            let alert: UIAlertController = UIAlertController(title: titles[i].0, message: titles[i].1, preferredStyle:  UIAlertController.Style.alert)
            let defaultAction: UIAlertAction = UIAlertAction(title: titles[i].2, style: UIAlertAction.Style.default, handler: { (action: UIAlertAction!) -> Void in
                // do nothing
            })
            alert.addAction(defaultAction)
            present(alert, animated: true, completion: nil)
            return
        }
        #if false // これだと単独の絵文字しか追加できないので、下記で修正する
        if var title = sender.currentTitle, let unicodeScalarValue = title.unicodeScalars.first?.value, let unicodeScalar = UnicodeScalar(unicodeScalarValue) { // 絵文字のボタンが押されたら、その文字コードとスカラー文字を取得
            if unicodeScalarValueRangeOfEMF.contains(unicodeScalarValue) { // 文字コードがスキンカラーなら、
                title = "∙" + title // 分かりやすさのため（かつ、意図せず合成されてしまうため）前置ドット演算子を追加
            }
            scalarLabel.text?.append(title)
            nativeLabel.text?.unicodeScalars.append(unicodeScalar)
        } // 合成前の文字列には絵文字をそのまま連結して、合成後の文字列にはスカラー文字を連結
        #else // こちらだと単独の絵文字だけでなく合成済みの絵文字も追加できるように修正した
        if let title = sender.currentTitle { // 絵文字のボタンが押されたら、その文字コードとスカラー文字を取得
            var isSkin = false
            if let unicodeScalarValue = title.unicodeScalars.first?.value, unicodeScalarValueRangeOfEMF.contains(unicodeScalarValue) { // 最初の文字コードがスキンカラーなら、
                isSkin = true
            }
            scalarLabel.text?.append(isSkin ? "∙" + title : title) // 分かりやすさのため（かつ、意図せず合成されてしまうため）前置ドット演算子を追加
            nativeLabel.text?.unicodeScalars.append(contentsOf: title.unicodeScalars)
        } // 合成前の文字列には絵文字をそのまま連結して、合成後の文字列にはスカラー文字（列）を連結
        #endif

        self.view.endEditing(true) // キーボードを閉じるため
    }
    @IBAction func spacialButtonTouchUpInside(_ sender: UIButton) {
        if let title = sender.currentTitle, let unicodeScalarValue = specialUnicodeScalarValues[title], let unicodeScalar = UnicodeScalar(unicodeScalarValue) { // (演算子と見做す)特殊文字が押されたら、辞書 specialUnicodeScalarValues から、対応する文字コードとスカラー文字を取得
            scalarLabel.text?.append(title)
            nativeLabel.text?.unicodeScalars.append(unicodeScalar)
        } // 合成前の文字列には特殊文字をそのまま連結して、合成後の文字列にはスカラー文字を連結
    }
    @IBAction func deleteButtonTouchUpInside(_ sender: UIButton) {
        //if scalarLabel.text == nil || scalarLabel.text!.isEmpty { return } // 合成前の文字列が nil や空なら return
        guard scalarLabel.text != nil && !scalarLabel.text!.isEmpty else { return } // 上記と等価
        var isSkin = false
        if unicodeScalarValueRangeOfEMF.contains(scalarLabel.text!.last!.unicodeScalars.last!.value) &&
            scalarLabel.text!.count > 1 {
            /* (注) 二つ目の last は本来 first であるべきだが、バグなのかそれでは意図した通りには動作しない(Swift5, Xcode10.3)ので、このようにしてある。バグ修正されたとしても、おそらくこのままでこの通りに動作すると思われる。*/
                isSkin = true
        }
        scalarLabel.text!.removeLast() // ⌫ ボタンが押されたら、合成前の文字列の末尾一文字を削除して、
        nativeLabel.text?.removeAll() // 合成後は文字列は消去
        if isSkin, let c = scalarLabel.text!.last, c == "∙" {
            /* (注) よって、現状(Swift5, Xcode10.3)では、ここには来れない！が、念の為、将来のバグ修正後に対応するため、以下を行う。 */
            scalarLabel.text!.removeLast() // 末尾の "∙" を除去
        }
        for c in scalarLabel.text! { // 合成前の文字列を一文字ずつループ
            let unicodeScalarValue = specialUnicodeScalarValues[String(c)] ?? c.unicodeScalars.first!.value
            if let unicodeScalar = UnicodeScalar(unicodeScalarValueRangeOfAlternateAZ.contains(unicodeScalarValue) ? // 代用大文字アルファベットなら
                unicodeScalarValue - unicodeScalarValueRangeOfAlternateAZ.lowerBound + unicodeScalarValueRangeOfSpecialAZ.lowerBound : unicodeScalarValue // 文字コードを特殊大文字アルファベットに変換したもの、それ以外なら文字コードから対応するスカラー文字を取得
                ) {
                nativeLabel.text?.unicodeScalars.append(unicodeScalar)
            } // 合成後の文字列にスカラー文字を連結
        }
    }
    @IBAction func specialTextFieldDidEndOnExit(_ sender: UITextField) {
        //if sender.text == nil || sender.text!.isEmpty { return } // 入力された文字列が nil や空なら return
        guard sender.text != nil && !sender.text!.isEmpty else { return } // 上記と等価
        if sender.text!.allSatisfy({ $0.isUppercase }) { // 入力された文字列がすべて通常大文字アルファベットなら、
            for c in sender.text! { // 入力された文字列を一文字ずつループ
                let alternateUnicodeScalarValue = c.unicodeScalars.first!.value - unicodeScalarValueRangeOfNormalAZ.lowerBound + unicodeScalarValueRangeOfAlternateAZ.lowerBound // 代用大文字アルファベットの文字コードに変換して、
                if let alternateUnicodeScalar = UnicodeScalar(alternateUnicodeScalarValue) { // そのスカラー文字が得られたら、
                    scalarLabel.text?.append(String(alternateUnicodeScalar)) // 合成前の文字列に連結
                }
                let unicodeScalarValue = c.unicodeScalars.first!.value - unicodeScalarValueRangeOfNormalAZ.lowerBound + unicodeScalarValueRangeOfSpecialAZ.lowerBound // 特殊大文字アルファベットの文字コードに変換して、
                if let unicodeScalar = UnicodeScalar(unicodeScalarValue) { // そのスカラー文字が得られたら、
                    nativeLabel.text?.unicodeScalars.append(unicodeScalar) // 合成後の文字列に連結
                }
            }
        }
        else { // それ以外なら、
            scalarLabel.text?.append(contentsOf: sender.text!)
            nativeLabel.text?.append(contentsOf: sender.text!)
        } // 合成前の文字列と合成後の文字列に、そのまま、連結
    }
    
}

