# coding:utf-8
# pip3 install xlrd==1.2.0

import json
import sys, os, shutil
import importlib.util, importlib.metadata
import subprocess
import pathlib
import argparse
from time import time

g_inputPath = ""
g_outputPath = ""
g_isFromUI = False
g_integerPath = ["err.prismCode"]
g_trimedPath = ["err.prismName"]
g_extra_path_is_str = ['extra', 'alert']

def check_install_package(package_name, version=None):
	def installPack():
		scriptStr = f"{sys.executable} -m pip install --force-reinstall {package_name}"
		if version:
			scriptStr += "=="+version
		if subprocess.call(scriptStr,shell=True) != 0:
			print(f"{package_name} is install failed")
	if importlib.util.find_spec(package_name) is None:
		installPack()
	elif version != None and importlib.metadata.version(package_name) != version:
		installPack()
check_install_package("xlrd", "1.2.0")
check_install_package("requests")

import xlrd
import requests

class multidict(dict):
	def __getitem__(self, item):
		try:
			return dict.__getitem__(self, item)
		except KeyError:
			value = self[item] = type(self)()
			return value

def create_json_dict_multi(keys:list, values):
	json_dict = {}
	for i in range(len(keys)):
		current_dict = json_dict
		key_parts = keys[i].split('.')
		for part in key_parts[:-1]:
			if part not in current_dict:
				current_dict[part] = {}
			current_dict = current_dict[part]

		valueData = values[i]
		if keys[i] not in g_integerPath:
			valueData = str(valueData)
			if keys[i] in g_trimedPath:
				valueData = valueData.strip()

		if keys[i] == "api.statusCode":
			key_parts[-1] = "$statusCode"

		if isinstance(valueData, str):
			if valueData == "" or valueData == "*":
				continue

		current_dict[key_parts[-1]] = valueData
	return json_dict

def create_json_dict_single(json_dict, keys:list, value):
	tmp_data = json_dict
	for key in keys[:-1]:
		tmp_data = tmp_data[key]
	tmp_data[keys[-1]] = value

def writeJsonToFile(dicData):

	def clean(data):
		#remove empty and none
		if isinstance(data, dict):
			return {k: clean(v) for k, v in data.items() if v or v == 0}
		elif isinstance(data, list):
			return [clean(v) for v in data if v or v == 0]
		else:
			return data

	writePath = g_outputPath
	if writePath == "":
		print("output path is empty, use default path")
		writePath = os.path.join(pathlib.Path(__file__).parent.absolute(), "../../src/prism-live-studio/PRISMLiveStudio/prism-ui/resource/DefaultResources", "errorCode.json")
		writePath = os.path.abspath(writePath)

	versionTime = int(time())
	dicData["version"] = versionTime
	cleanDict = clean(dicData)
	cleanDict = clean(cleanDict) #again

	dictStr = json.dumps(cleanDict, indent=4, ensure_ascii=False)
	dictStr = dictStr.replace(r"\\n", r"\n").replace(r"\\t", r"\t")
	with open(writePath, 'w', encoding='utf-8') as f:
		f.write(dictStr)
	print(f"version: {versionTime}")
	print(f"wirte json to: {writePath}")

	if g_isFromUI == False:
		#backup excel
		backUpExcel = os.path.join(pathlib.Path(__file__).parent.absolute(), "../../docs", "PRISMLiveStudio_error_code.xlsx")
		shutil.copyfile(g_inputPath, backUpExcel)

def parseExcel(filePath=None):
	workbook = xlrd.open_workbook(file_contents=None, filename=filePath)
	_all = multidict()

	def readPathSheets():
		sheetObject = workbook.sheet_by_name(sheet_name=containSheetName)
		for x in range(0, ncols):
			_pathKey = sheetObject.cell_value(rowx=0, colx=x)
			if not _pathKey:
				continue
			_datas = []
			for y in range(1, nrows):
				_data = sheetObject.cell_value(rowx=y, colx=x)
				if not _data:
					break
				_data = str(_data)
				_datas.append(_data)
			parts = containSheetName.split(".")
			if containSheetName == "inherit":
				parts.insert(0, _pathKey)
			else:
				parts.extend(_pathKey.split("."))
			if set(g_extra_path_is_str) < set(parts):
				#extra alert use json not array
				if len(_datas) > 0:
					create_json_dict_single(_all, parts, _datas[0])
			else:
				create_json_dict_single(_all, parts, _datas)

	def readErrorSheets():
		_datas = []
		_keys = []
		for x in range(0, ncols):
			_key = sheetObject.cell_value(rowx=0, colx=x)
			_keys.append(_key)

		for y in range(1,nrows):
			_values = []
			for x in range(0, ncols):
				_data = sheetObject.cell_value(rowx=y, colx=x)
				ctype =  sheetObject.cell_type(rowx=y, colx=x)
				if ctype == 2 and _data % 1 == 0:
					_data = int(_data)
				# _values.append(str(_data))
				_values.append(_data)
			j =  create_json_dict_multi(_keys, _values)
			_datas.append(j)

		_nameList = containSheetName.split(".")
		create_json_dict_single(_all, _nameList, _datas)

	for containSheetName in workbook.sheet_names():
		if "Note" == containSheetName:
			continue
		sheetObject = workbook.sheet_by_name(sheet_name=containSheetName)
		nrows = sheetObject.nrows
		ncols = sheetObject.ncols
		if ".extra" in containSheetName:
			readPathSheets()
			continue
		readErrorSheets()
	writeJsonToFile(_all)

# sys.argv.append("-i=/Users/jimbo/Downloads/PRISMLiveStudio_ErrorCode (43).xlsx")
# sys.argv.append("-o=/Users/jimbo/Library/Application Support/PRISMLiveStudio/resources/library/Library_Policy_PC/errorCode.json")
# py /Users/jimbo/Documents/source/prism/prism-live-studio/build/common/errorExcel2Json.py -o="/Users/jimbo/Library/Application Support/PRISMLiveStudio/resources/library/Library_Policy_PC/errorCode.json" -i="/Users/jimbo/Downloads/PRISMLiveStudio_ErrorCode (43).xlsx"
if __name__ == '__main__':
	parser = argparse.ArgumentParser(description='download excel and transfer to json')
	parser.add_argument("-i", type=str, default='', help='input local excel file')
	parser.add_argument("-o", type=str, default='', help='output json filepath, instead of prism data path')
	parser.add_argument('--fromui', action='store_true', help='from ui action')

	args = parser.parse_args()
	g_inputPath = args.i
	g_outputPath = args.o
	g_isFromUI = args.fromui
	print("input: ", g_inputPath)
	print("output: ", g_outputPath)
	
	if g_inputPath != "" and not os.path.exists(g_inputPath):
		print("input path is not exists, exit.")
		sys.exit(1)

	if g_inputPath == "":
		print("input path is empty")
		sys.exit(1)

	parseExcel(filePath=g_inputPath)
