import sys, configparser, os, time, unicodedata, MySQLdb

from PyQt5.QtWidgets import (QVBoxLayout, QLineEdit,QGridLayout,
 QApplication, QLabel, QMenu, QWidget, QHBoxLayout,QDialog,
 QAction, QTextEdit,QPushButton, qApp, QMessageBox, QInputDialog,
 QMainWindow, QFrame, QFileDialog, QCheckBox, QProgressBar,
 QListWidget, QCompleter, QComboBox, QTreeView,QAbstractItemView,
 QToolTip,QRadioButton,QButtonGroup)
from PyQt5.QtGui import (QIcon, QFont, QColor, QPixmap, QDrag, QPainter,
 QBrush, QPen,QStandardItem,QStandardItemModel,)
from PyQt5.QtCore import (QCoreApplication, Qt, QObject, pyqtSignal,
 QMimeData, QAbstractItemModel,QModelIndex)

from mysql_fasttext import Mysql_Fasttext
from write_project_ini import write_pro_ini
from mysql_learn_sampling import learn_sampling
from evaluation_test import evaluation
from main_config import main_Config
from vector_initialize import mysql_initialize

class distirbuted_learn_SubWindow(QWidget):

    def __init__(self, project):
        super().__init__()

        self.project = project
        self.distributed_window()

    def distributed_window(self):
        self.w=QDialog()

        label=QLabel("fasttextの設定")

        min_count_h_box=QHBoxLayout()
        min_label=QLabel("最小出現回数")
        min_label.setToolTip("出現回数が何回以上の単語を分析に使用しますか?")
        self.min=QLineEdit()
        self.min.setText("1")
        self.min.setToolTip("出現回数が何回以上の単語を分析に使用しますか?")
        min_count_h_box.addWidget(min_label)
        min_count_h_box.addStretch(1)
        min_count_h_box.addWidget(self.min)

        dim_h_box=QHBoxLayout()
        dim_label=QLabel("分散表現の次元数")
        dim_label.setToolTip("分散表現を何次元にしますか?")
        self.dim=QLineEdit()
        self.dim.setText("100")
        self.dim.setToolTip("分散表現を何次元にしますか?")
        dim_h_box.addWidget(dim_label)
        dim_h_box.addStretch(2)
        dim_h_box.addWidget(self.dim)

        labelB=QLabel("最大は300です")
        labelB.setAlignment(Qt.AlignRight)

        epoch_h_box=QHBoxLayout()
        epoch_label=QLabel("学習回数（epoch）")
        epoch_label.setToolTip("学習回数を設定します")
        self.epoch=QLineEdit()
        self.epoch.setText("5")
        self.epoch.setToolTip("5から50が推奨されています")
        epoch_h_box.addWidget(epoch_label)
        epoch_h_box.addStretch(2)
        epoch_h_box.addWidget(self.epoch)

        lr_h_box=QHBoxLayout()
        lr_label=QLabel("学習率（learning rate）")
        lr_label.setToolTip("学習率を設定します")
        self.lr=QLineEdit()
        self.lr.setText("0.1")
        self.lr.setToolTip("0.1から1.0が推奨されています")
        lr_h_box.addWidget(lr_label)
        lr_h_box.addStretch(2)
        lr_h_box.addWidget(self.lr)

        word_ngram_h_box=QHBoxLayout()
        word_ngram_label=QLabel("単語 N-gram")
        word_ngram_label.setToolTip("単語 N-gramを設定します")
        self.word_ngram=QLineEdit()
        self.word_ngram.setText("1")
        self.word_ngram.setToolTip("1から5が推奨されています")
        word_ngram_h_box.addWidget(word_ngram_label)
        word_ngram_h_box.addStretch(2)
        word_ngram_h_box.addWidget(self.word_ngram)

        ch_ngram_h_box=QHBoxLayout()
        ch_ngram_label=QLabel("文字Ngram")
        ch_ngram_label.setToolTip("文字Ngramを設定します")
        self.min_ngram=QLineEdit()
        self.min_ngram.setText("0")
        self.min_ngram.setToolTip("1から5が推奨されています")
        self.max_ngram=QLineEdit()
        self.max_ngram.setText("0")
        self.max_ngram.setToolTip("1から5が推奨されています")
        mark=QLabel("~")
        ch_ngram_h_box.addWidget(ch_ngram_label)
        ch_ngram_h_box.addStretch(1)
        ch_ngram_h_box.addWidget(self.min_ngram)
        ch_ngram_h_box.addWidget(mark)
        ch_ngram_h_box.addWidget(self.max_ngram)

        learn_h_box=QHBoxLayout()
        learn_label=QLabel("何%のテキストを教師用として使用しますか?")
        self.learn_count=QLineEdit()
        self.learn_count.setText("90")
        learn_per_label=QLabel("%")
        learn_h_box.addWidget(learn_label)
        learn_h_box.addWidget(self.learn_count)
        learn_h_box.addWidget(learn_per_label)

        result_h_box=QHBoxLayout()
        result_label=QLabel("適合率は")
        self.result_num=QLabel()
        #per_label=QLabel("%でした")
        result_h_box.addWidget(result_label)
        result_h_box.addWidget(self.result_num)
        #result_h_box.addWidget(per_label)

        button_h_box=QHBoxLayout()
        process_button=QPushButton("実行")
        process_button.clicked.connect(self.branch)
        cancelB=QPushButton("閉じる")
        cancelB.clicked.connect(self.w.close)
        button_h_box.addStretch(2)
        button_h_box.addWidget(process_button)
        button_h_box.addWidget(cancelB)

        main_v_layout=QVBoxLayout()
        main_v_layout.addLayout(min_count_h_box)
        main_v_layout.addLayout(dim_h_box)
        main_v_layout.addWidget(labelB)
        main_v_layout.addLayout(epoch_h_box)
        main_v_layout.addLayout(lr_h_box)
        main_v_layout.addLayout(word_ngram_h_box)
        #main_v_layout.addLayout(ch_ngram_h_box)
        main_v_layout.addStretch(1)
        main_v_layout.addLayout(learn_h_box)
        main_v_layout.addStretch(1)
        main_v_layout.addLayout(result_h_box)
        main_v_layout.addStretch(1)
        main_v_layout.addLayout(button_h_box)


        self.w.setGeometry(300, 300, 400, 400)
        self.w.setWindowTitle('分散表現の取得(supervised)')
        self.w.setLayout(main_v_layout)

    def branch(self):

        cfg=configparser.ConfigParser()
        file_path = self.project + ".ini"
        cfg.read(file_path)
        sampling=cfg['project']["sample"]
        label_count=cfg['project']["nums_of_label"]

        if int(label_count) == 0:
            #print("ラベルのないデータは使用できません")
            message=QMessageBox.information(self, "お知らせ","ラベルのないデータは使用できません", QMessageBox.Ok)

            self.w.close()
        elif int(label_count) == 1:
            #print("ラベルがひとつしか登録されていませんので、検証できません")
            message=QMessageBox.information(self, "お知らせ","ラベルがひとつしか登録されていませんので、検証できません", QMessageBox.Ok)

            self.w.close()
        else:
            mincount = self.min.text()
            dim = self.dim.text()
            epoch = self.epoch.text()
            lr = self.lr.text()
            word_ngram = self.word_ngram.text()
            minn = self.min_ngram.text()
            maxn = self.max_ngram.text()

            if int(sampling) == 0:
                sampling_dialog = QMessageBox.question(self, "Qestion","サンプリングしていないデータを使用しますか？",
                QMessageBox.Yes | QMessageBox.No,QMessageBox.No)

                if sampling_dialog == QMessageBox.No:
                    pass
                else:
                    if dim.isdigit() and mincount.isdigit():
                        if int(dim) >300:
                            #print("300以下で設定してください")
                            message=QMessageBox.information(self,"お知らせ", "300以下で設定してください", QMessageBox.Ok)

                        else:
                            self.process(self.project, mincount, dim, epoch, lr, word_ngram, minn, maxn, sampling)
                    else:
                        #print("数字を入力してください")
                        message=QMessageBox.information(self,"お知らせ", "数字を入力してください", QMessageBox.Ok)
            elif int(sampling) == 1:
                if int(dim) >300:
                    #print("300以下で設定してください")
                    message=QMessageBox.information(self,"お知らせ", "300以下で設定してください", QMessageBox.Ok)
                else:
                    self.process(self.project, mincount, dim, epoch, lr, word_ngram, minn, maxn, sampling)
            else:
                sampling_dialog = QMessageBox.question(self, "Qestion","このプロジェクトはすでに検証済みです。再検証しますか？",
                QMessageBox.Yes | QMessageBox.No,QMessageBox.No)

                if sampling_dialog == QMessageBox.No:
                    pass
                else:
                    if int(dim) >300:
                        #print("300以下で設定してください")
                        message=QMessageBox.information(self,"お知らせ", "300以下で設定してください", QMessageBox.Ok)
                    else:
                        write_pro_ini(self.project).main(sample = str(int(sampling) - 10))
                        time.sleep(0.1)
                        cfg=configparser.ConfigParser()
                        file_path = self.project + ".ini"
                        cfg.read(file_path)
                        sampling=cfg['project']["sample"]
                        self.process(self.project, mincount, dim, epoch, lr, word_ngram, minn, maxn, sampling)

    def process(self, project, mincount, dim, epoch, lr, word_ngram, minn, maxn, sampling):

        time.sleep(0.1)
        count = self.learn_count.text()
        count = unicodedata.normalize("NFKC", count)
        if count.isdigit():

            reply = QMessageBox.question(self, '処理を開始しますか？',
                "この処理は時間がかかります<br>処理を開始しますか?", QMessageBox.Yes |
                QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.Yes:

                mysql_initialize(project)

                learn_sampling(project, count, sampling)
                count_texts_analysis=self.count_sampling(project)

                if int(count) == 100:
                    pass
                else:
                    write_pro_ini(project).main(sample = str(int(sampling) + 10))
                #count_texts_analysis = count_texts_analysis)   #iniファイルのサンプリングに学習済み(2)を登録

                time.sleep(0.1)
                Mysql_Fasttext(project, mincount, dim, epoch, lr, word_ngram, minn, maxn, "1") #from mysql_fasttext 教師データをfasttextへ 最後の引数１はsupervisedで分散表現を獲得することを意味している
                time.sleep(0.1)

                if int(count) == 100:
                    sampled_or_not = str(int(sampling))
                    self.result_num.setText("テストしていません")
                    result = "適合率のテストせず"
                else:
                    result = evaluation(project)
                    self.result_num.setText(result + " %でした")
                    sampled_or_not = str(int(sampling) + 10)
                    #result = str(result + "%")
                    #print(dim)
                    #print(result)

                write_pro_ini(project).main(sample = sampled_or_not,
                count_texts_analysis = count_texts_analysis,
                discrimination="0",
                train_test = str(result),
                dimensions = str(dim))

                #print(result)

                time.sleep(0.2)
                message=QMessageBox.information(self,"お知らせ", "処理が終了しました", QMessageBox.Ok)
            else:
                pass

        else:
            #print("学習データ数は数字を入力してください")
            message=QMessageBox.information(self,"お知らせ", "学習データ数は数字を入力してください", QMessageBox.Ok)

    def count_sampling(self, project):
#        config=configparser.ConfigParser()
#        config.read('main.ini')
#        mysql_id=config['settings']["id"]
#        mysql_pass=config['settings']["pass"]
        mysql_id, mysql_pass, projects, root_path, using_os = main_Config()
        try:
            conn=MySQLdb.connect(db=project, user=mysql_id, passwd=mysql_pass, charset="utf8mb4")
            cursor=conn.cursor()

            sql="select count(*) from text_table where train_test_data = 1"
            cursor.execute(sql)
            res=list(cursor.fetchall())
            res=str((res[0])[0])
            time.sleep(0.1)

            return res

            conn.commit()
            cursor.close()
            conn.close()

        except Exception as e:
            print(e)

    def show(self):
        self.w.exec_()

if __name__=="__main__":
    app=QApplication(sys.argv)

    project="tttt"

    ex= distirbuted_learn_SubWindow(project)
    distirbuted_learn_SubWindow(project).show()
    sys.exit(app.exec_())
