#!/usr/bin/env python3
# -*- coding:utf-8 -*-


try:
    import sys
    import importlib

    importlib.reload(sys)
    import json
    import time
    from gspylib.inspection.common import SharedFuncs
    from gspylib.inspection.common.ExcelWriter import ExcelWriter
    from multiprocessing.dummy import Pool as ThreadPool
except ImportError as ie:
    sys.exit("[GAUSS-52200] : Unable to import module: %s." % str(ie))


class ResultStatus(object):
    OK = "OK"
    NA = "NA"
    WARNING = "WARNING"
    NG = "NG"
    ERROR = "ERROR"


class LocalItemResult(object):
    '''
    the check result running on one host
    '''

    def __init__(self, name, host):
        self.name = name
        self.host = host
        self.raw = ""
        self.rst = ResultStatus.NA
        self.val = ""
        self.checkID = None
        self.user = None

    def output(self, outPath):
        u"""
[HOST]  {host}
[NAM]   {name}
[RST]   {rst}
[VAL]
{val}
[RAW]
{raw}
        """
        val = self.val if self.val else ""
        raw = self.raw if self.raw else ""
        try:
            content = self.output.__doc__.format(name=self.name, rst=self.rst, host=self.host, val=val, raw=raw)
        except Exception:
            content = self.output.__doc__.encode('utf-8').format(name=self.name, rst=self.rst, host=self.host, val=val,
                                                                 raw=raw)
        fileName = "%s_%s_%s.out" % (self.name, self.host, self.checkID)
        # output the result to local path
        SharedFuncs.writeFile(fileName, content, outPath, 600, self.user)


class ItemResult(object):
    def __init__(self, name):
        self.name = name
        self._items = []
        self.rst = ResultStatus.NA
        self.standard = ""
        self.suggestion = ""
        self.category = 'other'
        self.analysis = ""

    def __iter__(self):
        return iter(self._items)

    def __getitem__(self, idx):
        return self._items[idx]

    def append(self, val):
        self._items.append(val)

    def formatOutput(self, detail=False):
        result = u"{name:.<25}...............{rst:.>6}".format(name=self.name, rst=self.rst)
        result += u"\r\n%s\r\n" % self.analysis
        return result

    def getLocalItems(self):
        return self._items

    @staticmethod
    def parse(contentList, itemName):
        itemResult = ItemResult(itemName)
        try:
            pool = ThreadPool(len(contentList))
            localItems = pool.map(ItemResult.__parseOneHost, contentList)
            pool.close()
            pool.join()
        except Exception as ex:
            raise Exception(str(ex))
        for localItem in localItems:
            itemResult.append(localItem)
        return itemResult

    @staticmethod
    def __parseOneHost(content):
        localItemResult = None
        host = None
        idx = 0
        length = len(content.splitlines())
        totallist = content.splitlines()
        while (idx < length):
            current = totallist[idx]
            if (not current):
                idx += 1
                continue
            elif (current.startswith('[HOST]')):
                host = current.split()[1].strip()
                idx += 1
            elif (current.startswith('[NAM]')):
                name = current.split()[1].strip()
                localItemResult = LocalItemResult(name, host)
                idx += 1
            elif (current.startswith('[RST]')):
                localItemResult.rst = current.split()[1].strip()
                idx += 1
            elif (current.startswith('[VAL]')):
                nextIdx = totallist.index('[RAW]', idx)
                tmplist = totallist[idx + 1:nextIdx]
                localItemResult.val = ItemResult.__parseMultiLine(tmplist)
                idx = nextIdx
            elif (current.startswith('[RAW]')):
                tmplist = totallist[idx + 1:]
                localItemResult.raw = ItemResult.__parseMultiLine(tmplist)
                idx = length
        return localItemResult

    @staticmethod
    def __parseMultiLine(lines):
        vals = []
        starter = ('[HOST]', '[NAM]', '[RST]', '[VAL]', '[RAW]')
        for line in lines:
            current = line.strip()
            if (current.startswith(starter)):
                break
            else:
                vals.append(current)
        return "\n".join(vals)


class CheckResult(object):
    def __init__(self):
        self._items = []

    def __iter__(self):
        return iter(self._items)

    def __getitem__(self, idx):
        return self._items[idx]

    def append(self, val):
        self._items.append(val)

    def outputStatistic(self):
        ok = 0
        warning = 0
        ng = 0
        error = 0
        for i in self._items:
            if (i.rst == ResultStatus.ERROR):
                error += 1
            elif (i.rst == ResultStatus.NG):
                ng += 1
            elif (i.rst == ResultStatus.WARNING):
                warning += 1
            else:
                ok += 1
        okMsg = " Success:%s " % ok if ok > 0 else ""
        warningMsg = " Warning:%s " % warning if warning > 0 else ""
        ngMsg = " NG:%s " % ng if ng > 0 else ""
        errorMsg = " Error:%s " % error if error > 0 else ""
        result = ""
        result += "Failed." if (ng + error) > 0 else "Success."
        result += "\tAll check items run completed. Total:%s  %s %s %s %s" % (
            ok + warning + ng + error, okMsg, warningMsg, ngMsg, errorMsg)
        return result

    def outputRaw(self):
        u"""
{date} [NAM] {name}
{date} [STD] {standard}
{date} [RST] {rst}
{val}
{date} [RAW]
{raw}
        """
        result = ""
        for i in self._items:
            for j in i._items:
                t = time.localtime(time.time())
                dateString = time.strftime("%Y-%m-%d %H:%M:%S", t)
                rst = j.rst
                if j.rst == ResultStatus.NA:
                    rst = "NONE"
                elif j.rst == ResultStatus.WARNING or j.rst == ResultStatus.ERROR:
                    rst = "NG"
                result += self.outputRaw.__doc__.format(date=dateString, name=j.name, standard=i.standard.decode(),
                                                        rst=rst, val=j.val, raw=j.raw)
                result = "%s\r\n" % result
        return result

    def outputResult(self):
        result = ""
        for i in self._items:
            result = "%s%s" % (result, i.formatOutput())
            result = "%s\r\n" % result
        result += self.outputStatistic()
        return result

    def outputExcel(self, fileName):
        writer = ExcelWriter(fileName)
        for itemResult in self._items:
            name = itemResult.name
            category = itemResult.category
            std = str(itemResult.standard, encoding='utf-8')
            rst = itemResult.rst
            analysis = itemResult.analysis
            if itemResult.suggestion:
                suggestion = str(itemResult.suggestion, encoding='utf-8')
            else:
                suggestion = ""
            writer.writecheckdetail(name, category, "Summary", std, rst, "In node result", "In node result", analysis,
                                    suggestion)
            for localitem in itemResult:
                host = localitem.host
                rstd = localitem.val
                raw = localitem.raw
                rst = localitem.rst
                writer.writecheckdetail(name, category, host, std, rst, rstd, raw, analysis, suggestion)
        writer.close()

    def outputJson(self):
        resultDic = {}
        for itemResult in self._items:
            resultDic['name'] = itemResult.name
            resultDic['category'] = itemResult.category
            resultDic['std'] = itemResult.standard
            resultDic['rst'] = itemResult.rst
            resultDic['analysis'] = itemResult.analysis
            resultDic['suggestion'] = itemResult.suggestion
            localList = []
            for localitem in itemResult:
                local = {'host': localitem.host, 'rstd': localitem.val, 'raw': localitem.raw}
                localList.append(local)
            resultDic['hosts'] = localList
        return json.dumps(resultDic, indent=2)
