#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
M2PlotPlusCui.py
ECM表示のCUI
"""
from __future__ import print_function
import sys
import os
import Manyo
# from PySide import (QtCore, QtGui)
# from ui_M2PlotPlus import Ui_MainWindow
# import U2IF
from uGao.uGaoUtil import STRING_TO_REPLACE_SPACE, STRING_TO_REPLACE_LF, TempFile
# from os.path import expanduser
# import numpy as np
# import vis.MPlot as mp
from uGao.QtCom import CommQt

#######################################
#  M2PlotPlusCui.py
#######################################

######################################################


class M2PlotPlusCui(object):
    """
    """
    #########################################

    def __init__(self, data=None, closeFlag=True):
        """
        コンストラクタ
        @param data (ElementContainerArray/Matrix or None) data to be plotted
        @closeFlag (bool) Close plotter or not when parent process dies
        @retval None
        """
        self.plot = None
        # テンポラリファイルクラスのインスタンス取得
        self.tp = TempFile()

        # プロッタの作成
        self.Start(data, closeFlag)

    #########################################
    def Start(self, data=None, closeFlag=True):
        """
        プロッタを追加し、カレントプロッタとする
        @param data (ElementContainerArray/Matrix or None) data to be plotted
        @closeFlag (bool) Close plotter or not when parent process dies
        @retval None
        """
        pno = 1
        strPno = "%d" % (pno)

        if closeFlag:
            cflag = "True"
        else:
            cflag = "False"

        arg = ["M2PlotPlus.py", strPno, cflag]
        # プロセスID とプロッタ番号からポート番号を生成
        pxx = (os.getpid() % 500) * 20
        portno = 10000 + pxx + pno

        # GUI通信クラスのインスタンス取得
        p = CommQt()

        # プロセス生成と通信接続に成功したなら
        if p.NewComm(portno, arg):

            # 追加したプロッタをカレントプロッタとする。
            self.plot = p

            # データが指定されていたら
            if data is not None:
                # データを追加
                self.ChangeData(data)
        else:
            print("\nError!!  Cannot create a new plotter!!.")

    #########################################
    def ChangeData(self, data=None):
        """
        プロッタにデータを送付
        @param data (ElementContainerArray/Matrix or None) data to be plotted
        @retval None
        """
        if data is None:
            print("Data is empty")
            return

        isContainer = False
        ecType = 0  # means data is ElementContainerMatrix
        if isinstance(data, Manyo.ElementContainerMatrix):
            isContainer = True
            ecType = 0
        elif isinstance(data, Manyo.ElementContainerArray):
            isContainer = True
            ecType = 1
        else:
            print("Data is not ElementContainerMatrix nor ElementContainerArray.")
            return

        temppath = self.tp.GetTempName(".srlz")
        if temppath is None:
            # 異常終了
            print("\nError!! Cannot make a temporary file.")
            return
        # シリアライズ
        crw = Manyo.WriteSerializationFileBinary(temppath)
        crw.Save(data)
        del crw
        # コマンド作成(改行コード付)
        strCmd = "changedata %s %d\n" % (temppath, ecType)
        # コマンドの送信要求をカレントプロッタへ送る
        self.plot.PutCommand(strCmd)

    #########################################
    def SetDetectMapMode(self, isDetMap=True):
        """
        """
        if not isinstance(isDetMap, bool):
            return
        arg1 = "FALSE"
        if isDetMap:
            arg1 = "TRUE"

        # コマンド作成(改行コード付)
        strCmd = "detectmapmode %s\n" % (arg1)
        # コマンドの送信要求をカレントプロッタへ送る
        self.plot.PutCommand(strCmd)

    #########################################
    def ShowData(self, xkey="-", ykey="-", rkey="-", r_min=0.0, r_max=0.0):
        """
        Show data with given keys
        @param  xkey(str) Key of vector for X axis
        @param  ykey(str) Key of vector for Y axis
        @param  rkey(str) 3rd Key of vector for DetectMap mode
        @param r_min(float) range of 3rd vector
        @param r_max(float) range of 3rd vector
        @retval None
        """
        strCmd = "showdata %s %s %s %g %g\n" % (xkey, ykey, rkey, r_min, r_max)
        self.plot.PutCommand(strCmd)

    #########################################
    def SetLabels(self, xlabel="-", ylabel="-"):
        """
        Set Labels
        @param  xlabel(str) Label of X-axis
        @param  ylabel(str) Label of Y-axis
        @retval None
        """
        xlabel = xlabel.replace(" ", STRING_TO_REPLACE_SPACE)
        ylabel = ylabel.replace(" ", STRING_TO_REPLACE_SPACE)
        strCmd = "setlabels %s %s\n" % (xlabel, ylabel)
        self.plot.PutCommand(strCmd)

    #########################################
    def SetUnits(self, xunit="-", yunit="-"):
        """
        Set Units for axes
        @param  xunit(str) Unit for X-axis
        @param  yunit(str) Unit for Y-axis
        @retval None
        """
        xunit = xunit.replace(" ", STRING_TO_REPLACE_SPACE)
        yunit = yunit.replace(" ", STRING_TO_REPLACE_SPACE)
        strCmd = "setunits %s %s\n" % (xunit, yunit)
        self.plot.PutCommand(strCmd)

    #########################################
    def SetTitles(self, title="-", comment="-"):
        """
        Set Titles
        @param  title(str) Title for 2d plotting
        @param  comment(str) Comments for 2d plotting
        @retval None
        """
        title = title.replace(" ", STRING_TO_REPLACE_SPACE)
        title = title.replace("\n", STRING_TO_REPLACE_LF)
        comment = comment.replace(" ", STRING_TO_REPLACE_SPACE)
        comment = comment.replace("\n", STRING_TO_REPLACE_LF)
        strCmd = "settitles %s %s\n" % (title, comment)
        self.plot.PutCommand(strCmd)

    #########################################
    def SetSmoothing(self, isSmooth=False, windowVal=1, timesVal=1):
        """
        Set Smoothiing
        @param  isSmooth (bool) Smooth on or not
        @param windowVal (int) Window Size for smoothing
        @param timesVal (int) The number of times
        @retval None
        """
        if isSmooth:
            cSmooth = "True"
        else:
            cSmooth = "False"
        strCmd = "setsmooth %s %d %d\n" % (cSmooth, windowVal, timesVal)
        self.plot.PutCommand(strCmd)
    #########################################

    def SetWindowSize(self, width, height):
        """
        Set Window Size
        @param  width (int) window width
        @param  height (int) window height
        @retval None
        """
        try:
            p1 = int(width)
            p2 = int(height)
            strCmd = "setwindowsize %d %d\n" % (p1, p2)
            self.plot.PutCommand(strCmd)
        except:
            print("Invalid Arguments Error")
    #########################################

    def SetIntLog(self, flag=True):
        """
        Set log scale on Intensity
        @param flag (bool) True:On, False:Off
        @retval None
        """
        if flag:
            strCmd = "setlogscale Z True\n"
        else:
            strCmd = "setlogscale Z False\n"
        self.plot.PutCommand(strCmd)

    #########################################
    def SetXLog(self, flag=True):
        """
        Set log scale on X axis
        @param flag (bool) True:On, False:Off
        @retval None
        """
        if flag:
            strCmd = "setlogscale X True\n"
        else:
            strCmd = "setlogscale X False\n"
        self.plot.PutCommand(strCmd)

    #########################################
    def SetYLog(self, flag=True):
        """
        Set log scale on Y axis
        @param flag (bool) True:On, False:Off
        @retval None
        """
        if flag:
            strCmd = "setlogscale Y True\n"
        else:
            strCmd = "setlogscale Y False\n"
        self.plot.PutCommand(strCmd)

    #########################################
    def SetXaxisInversion(self, flag=True):
        """
        Set X axis inversion
        @param flag (bool) True:On, False:Off
        @retval None
        """
        if flag:
            strCmd = "setaxisinversion X True\n"
        else:
            strCmd = "setaxisinversion X False\n"
        self.plot.PutCommand(strCmd)

    #########################################
    def SetYaxisInversion(self, flag=True):
        """
        Set Y axis inversion
        @param flag (bool) True:On, False:Off
        @retval None
        """
        if flag:
            strCmd = "setaxisinversion Y True\n"
        else:
            strCmd = "setaxisinversion Y False\n"
        self.plot.PutCommand(strCmd)

    #########################################
    def SetIntScale(self, min_v=None, max_v=None):
        """
        Set scale range for Intensity
        When not given both arguments,like SetIntScale(), this turns over the auto scale mode.
        @param min_v (float) minumum of range / (None) use of auto scale value
        @param max_v (float) maximum of range / (None) use of auto scale value
        @retval None
        """
        if (min_v is None) and (max_v is None):
            strCmd = "setautoscale Z Turn\n"
            self.plot.PutCommand(strCmd)
            return

        try:
            if min_v is None:
                min_v = "None"
            else:
                min_v = "{:f}".format(float(min_v))
            if max_v is None:
                max_v = "None"
            else:
                max_v = "{:f}".format(float(max_v))
            strCmd = "setautoscale Z OFF\n"
            self.plot.PutCommand(strCmd)
            strCmd = "setaxisscale Z {} {}\n".format(min_v, max_v)
            self.plot.PutCommand(strCmd)
        except:
            print("SetIntScale param type is invalid.")
            return

    #########################################
    def SetXScale(self, min_v=None, max_v=None):
        """
        Set scale range for X axis
        When not given both arguments,like SetXScale(), Auto Xscale turns on.

        @param min_v (float) minumum of range / (None) use of auto scale value
        @param max_v (float) maximum of range / (None) use of auto scale value
        @retval None
        """
        if (min_v is None) and (max_v is None):
            strCmd = "setautoscale X Turn\n"
            self.plot.PutCommand(strCmd)
            return

        try:
            if min_v is None:
                min_v = "None"
            else:
                min_v = "{:f}".format(float(min_v))
            if max_v is None:
                max_v = "None"
            else:
                max_v = "{:f}".format(float(max_v))
            strCmd = "setautoscale X OFF\n"
            self.plot.PutCommand(strCmd)
            strCmd = "setaxisscale X {} {}\n".format(min_v, max_v)
            self.plot.PutCommand(strCmd)
        except:
            print("SetXScale param type is invalid.")
            return

    #########################################
    def SetYScale(self, min_v=None, max_v=None):
        """
        Set scale range for Y axis
        When not given both arguments,like SetYScale(), Auto Yscale turns on.

        @param min_v (float) minumum of range / (None) use of auto scale value
        @param max_v (float) maximum of range / (None) use of auto scale value
        @retval None
        """
        if (min_v is None) and (max_v is None):
            strCmd = "setautoscale Y Turn\n"
            self.plot.PutCommand(strCmd)
            return

        try:
            if min_v is None:
                min_v = "None"
            else:
                min_v = "{:f}".format(float(min_v))
            if max_v is None:
                max_v = "None"
            else:
                max_v = "{:f}".format(float(max_v))
            strCmd = "setautoscale Y OFF\n"
            self.plot.PutCommand(strCmd)
            strCmd = "setaxisscale Y {} {}\n".format(min_v, max_v)
            self.plot.PutCommand(strCmd)
        except:
            print("SetYScale param type is invalid.")
            return

    #########################################
    def SetIntScaleAuto(self, flag=True):
        """Set auto scale mode.

        @param flag (bool) True: auto scale mode of the intensity is on.
        @retval None
        """
        if isinstance(flag, str) and flag.upper() in ["ON", "OFF"]:
            strCmd = "setautoscale Z {}\n".format(flag.upper())
        elif isinstance(flag, bool):
            if flag:
                strCmd = "setautoscale Z ON\n"
            else:
                strCmd = "setautoscale Z OFF\n"
        else:
            raise UserWarning("SetIntScaleAuto : Invalid argument {}.".format(flag))

        self.plot.PutCommand(strCmd)
        return

    #########################################
    def SetXScaleAuto(self, flag=True):
        """Set auto scale mode for X axis.

        @param flag (bool) True: auto scale mode of the intensity is on.
        @retval None
        """
        if isinstance(flag, str) and flag.upper() in ["ON", "OFF"]:
            strCmd = "setautoscale X {}\n".format(flag.upper())
        elif isinstance(flag, bool):
            if flag:
                strCmd = "setautoscale X ON\n"
            else:
                strCmd = "setautoscale X OFF\n"
        else:
            raise UserWarning("SetXScaleAuto : Invalid argument {}.".format(flag))

        self.plot.PutCommand(strCmd)
        return

    #########################################
    def SetYScaleAuto(self, flag=True):
        """Set auto scale mode for Y axis.

        @param flag (bool) True: auto scale mode of the intensity is on.
        @retval None
        """
        if isinstance(flag, str) and flag.upper() in ["ON", "OFF"]:
            strCmd = "setautoscale Y {}\n".format(flag.upper())
        elif isinstance(flag, bool):
            if flag:
                strCmd = "setautoscale Y ON\n"
            else:
                strCmd = "setautoscale Y OFF\n"
        else:
            raise UserWarning("SetYScaleAuto : Invalid argument {}.".format(flag))

        self.plot.PutCommand(strCmd)
        return

    #########################################
    def SetCurrentKey(self, key):
        """
        Set a current key [tito 190313]
        @param  title (str) key
        @retval None
        """
        strCmd = "setcurrentkey {0}\n".format(key)
        self.plot.PutCommand(strCmd)

    #########################################
    def SetWindowTitle(self, title):
        """
        Set Window Title
        @param  title (str) window title
        @retval None
        """
        try:
            title = str(title)
            strCmd = "setwindowtitle %s\n" % (title)
            self.plot.PutCommand(strCmd)
        except:
            print("Invalid Arguments Error")

    #########################################
    def SaveAsText(self, filename, dQ=0.0, isIgnoreMask=False, maskinfo=[False, 0.0]):
        """
        Save data as a text file
        @param filename (str) path/to/file
        @param dQ (float) binning of Q at elastic position which is used for inelastic powder data
        @param isIgnoreMask (bool) Whether points witch intensity is mask value are ignore ( not saved in file ) or not
        @param maskinfo (list of bool and float) [True, <val>] is to replace mask value to <val>
        @retval None
        """
        if len(maskinfo) != 2:
            raise UserWarning(
                "M2PlotPlusCui::SaveAsText >> maskinfo is invalid")
        try:
            filename = str(filename)
            if isIgnoreMask:
                ign = "True"
            else:
                ign = "False"
            if maskinfo[0]:
                msk = "True"
            else:
                msk = "False"
            mskval = float(maskinfo[1])
            strCmd = "saveastext {} {} {} {} {}\n".format(
                filename, dQ, ign, msk, mskval)
            self.plot.PutCommand(strCmd)
        except:
            print("M2PlotPlusCui::SaveAsText >> invalid parameters")

    #########################################
    def SetSliceMethod(self, isAve):
        """
        Set Slice method to add data
        @param  isAve (bool) True:average mode, False:summation mode
        @retval 無し
        """
        flag = None
        try:
            if isinstance(isAve, bool):
                if isAve:
                    flag = "true"
                else:
                    flag = "false"
            elif isinstance(isAve, str):
                if isAve.lower() == "true":
                    flag = "true"
                elif isAve.lower() == "false":
                    flag = "false"
                else:
                    pass
            else:
                print("Invalid Arguments Error")

            if flag is not None:
                strCmd = "setslicemethod %s\n" % (flag)
                self.plot.PutCommand(strCmd)

        except:
            print("Invalid Arguments Error")

    #########################################
    def Close(self):
        """
        Close M2Plot+
        @param None
        @retval None
        """
        self.plot.PutCommand("close\n")
