#!/usr/bin/env python3
import openpyxl
import os
import sys
import json
from openpyxl.worksheet.worksheet import Worksheet
import json

#TODO: 시나리오마다 바뀔 수 있음
nationLevelMap = {
    '황제':7,
    '왕':6,
    '공':5,
    '주목':4,
    '주자사':3,
    '군벌':2,
    '호족':1,
    '방랑군':0
}

xlsxpath = sys.argv[1]
print(xlsxpath)
wb = openpyxl.load_workbook(xlsxpath, read_only=True)

def parseConfig(configSheet: Worksheet):
    result = {}
    for row in configSheet.iter_rows(min_row=2, values_only=True):
        print(row)
        if len(row) < 4:
            continue
        varName = row[0]
        value = row[3]

        if value is None:
            continue

        if isinstance(value, float) and float(int(value)) == value:
            value = int(value)

        if isinstance(value, str):
            # json으로 변환 시도
            try:
                value = json.loads(value)
            except:
                values = value.split('\n')
                if len(values) > 1:
                    value = values

        varNames = varName.split('.')
        varNameCnt = len(varNames)
        target = result
        for idx, name in enumerate(varNames):
            if idx + 1 == varNameCnt:
                target[name] = value
                break
            if not name in target:
                target[name] = {}
            target = target[name]

    if 'useCharSetting' in result:
        if result['useCharSetting'] > 0:
            result['fiction'] = 0
        else:
            result['fiction'] = 1
        del result['useCharSetting']
    return result

def extractNationList(nationSheet: Worksheet):
    jsonNationList = []
    nationChiefInfo = {}

    for row in nationSheet.iter_rows(min_row=2, values_only=True):
        if len(row) < 8:
            continue

        if len(row) == 8:
            name, color, gold, rice, desc, tech, nationType, nationLevel = row
            cities = ''
        else:
            name, color, gold, rice, desc, tech, nationType, nationLevel, cities = row[:9]

        nationChiefInfo[name] = {}
        if len(row) >= 10:
            chief0 = str(row[9])
            if chief0:
                nationChiefInfo[name][chief0] = 12
        if len(row) >= 11:
            chief1 = str(row[10])
            if chief1:
                nationChiefInfo[name][chief1] = 11


        cities = list(map(str.strip, row[8].split(',')))

        if not cities:
            nationLevel = '방랑군'

        if nationLevel.isdigit():
            nationLevel = int(nationLevel)
        elif nationLevel in nationLevelMap:
            nationLevel = nationLevelMap[nationLevel]
        else:
            nationLevel = 1

        gold = int(gold)
        rice = int(rice)
        tech = int(tech)

        jsonNationList.append([name, color, gold, rice, desc, tech, nationType, nationLevel, cities])

    return jsonNationList, nationChiefInfo


def extractGeneralList(generalSheet: Worksheet, nationList={}, nationChiefInfo={}):
    nationInv = {'재야':0}
    for idx, nation in enumerate(nationList, 1):
        nationInv[nation[0]] = idx

    json_general_list = []
    names = {}
    for row_idx, row in enumerate(generalSheet.iter_rows(min_row=2, values_only= True)):
        if len(row) < 10:
            continue


        if len(row) < 13:
            row = list(row) + [None] * (13 - len(row))
        else:
            row = list(row[:13])

        #상성, 장수명, 전콘, 국가명, 도시, 통솔, 무력, 지력, 생년, 몰년, 성격, 고유특기, 고유대사
        declrow = [0, '', ('', str, int), ('', str, int), '', 10, 10, 10, 0, 0, '', '', '']
        for i, (raw_value, decl_type) in enumerate(zip(row, declrow)):
            if decl_type is None:
                continue
            if type(decl_type) is str:
                row[i] = str(raw_value or decl_type).strip()
                continue
            if type(decl_type) is int:
                if raw_value is None:
                    row[i] = 0
                elif type(raw_value) is int:
                    row[i] = raw_value
                elif type(raw_value) is str and raw_value.isdigit():
                    row[i] = int(raw_value)
                else:
                    raise RuntimeError('%d행 %d열 값이 숫자가 아닙니다: %s'%(row_idx+1, i+1, raw_value))
                continue

            if type(decl_type) is not tuple:
                raise RuntimeError('%d행 %d열 값이 잘못되었습니다: %s'%(row_idx+1, i+1, raw_value))

            if raw_value is not None and type(raw_value) not in decl_type:
                raise RuntimeError('%d행 %d열 값 타입이 이상합니다: %s'%(row_idx+1, i+1, raw_value))
            if raw_value is None:
                row[i] = decl_type[0]

            #상세 타입을 지정해야하지만... 귀찮다...
            if type(raw_value) is str:
                row[i] = raw_value.strip()
                continue

        상성: int
        장수명: str
        전콘: int or str
        국가명: int or str
        도시: str
        통솔: int
        무력: int
        지력: int
        생년: int
        몰년: int
        성격: str
        고유특기: str
        고유대사: str
        상성, 장수명, 전콘, 국가명, 도시, 통솔, 무력, 지력, 생년, 몰년, 성격, 고유특기, 고유대사 = row

        #이름
        장수명 = 장수명.strip()
        if 장수명 == '':
            continue
        print(장수명)
        #전콘
        if 전콘 == '':
            전콘 = None

        level = 0

        #국가
        국가명 = 국가명
        국가코드 = 0
        if 국가명 in nationInv:
            level = 1
            국가코드 = nationInv[국가명]
        else:
            국가코드 = 0
            if type(국가명) is str:
                if 국가명.isdigit():
                    국가코드 = int(국가명)
            elif type(국가명) is int:
                국가코드 = 국가명

            if 1 <= 국가코드 <= len(nationList):
                국가명 = nationList[국가코드 - 1][0]
                level = 1
            else:
                국가명 = ''
                level = 0

        if 도시 == '':
            도시 = None

        if level and 국가명 in nationChiefInfo:
            nationChiefDetail = nationChiefInfo[국가명]
            if 장수명 in nationChiefDetail:
                level = int(nationChiefDetail[장수명])

        if 성격 == '':
            성격 = None

        if 고유특기 == '':
            고유특기 = None

        if 고유대사 == '':
            고유대사 = None

        if 고유대사 is None:
            json_output = [상성, 장수명, 전콘, 국가코드, 도시, 통솔, 무력, 지력, level, 생년, 몰년, 성격, 고유특기]
        else:
            json_output = [상성, 장수명, 전콘, 국가코드, 도시, 통솔, 무력, 지력, level, 생년, 몰년, 성격, 고유특기, 고유대사]



        json_general_list.append(json_output)

        if 장수명 in names:
            raise RuntimeError('%s가 이미 있습니다!'%장수명)
        names[장수명] = 1
    return json_general_list, names


if '환경 변수' in wb:
    config = parseConfig(wb['환경 변수'])
    config['startYear'] -= 3
else:
    config = {
        'title':'타이틀'
    }

if '국가' in wb:
    nationInfo, nationChiefInfo = extractNationList(wb['국가'])
else:
    nationInfo = []
    nationChiefInfo = {}

generalList, names = extractGeneralList(wb['장수 목록'], nationInfo, nationChiefInfo)

with open('%s.json'%xlsxpath, 'wt', encoding='utf-8') as fp:
    fp.write(json.dumps(config, ensure_ascii=False, indent='    ')[:-2])
    fp.write(',\n')

    fp.write('    "nation":[\n        ')
    fp.write(',\n        '.join([json.dumps(nation, ensure_ascii=False) for nation in nationInfo]))
    fp.write('\n    ],\n')

    fp.write('    "diplomacy":[],\n')

    fp.write('    "general":[\n        ')
    fp.write(',\n        '.join([json.dumps(general, ensure_ascii=False) for general in generalList]))
    fp.write('\n    ]')

    names2 = []
    names3 = []
    if '확장 장수 목록' in wb.sheetnames:
        generalExList, names2 = extractGeneralList(wb['확장 장수 목록'], nationInfo, nationChiefInfo)

        for name in names2:
            if name in names:
                raise RuntimeError('%s가 일반 장수 및 확장 장수에 모두 있습니다!'%name)

        fp.write(',\n    "general_ex":[\n        ')
        fp.write(',\n        '.join([json.dumps(general, ensure_ascii=False) for general in generalExList]))
        fp.write('\n    ]')

    if '빙의 불가 장수 목록' in wb.sheetnames:
        generalNeutralList, names3 = extractGeneralList(wb['빙의 불가 장수 목록'], nationInfo, nationChiefInfo)

        for name in names3:
            if name in names:
                raise RuntimeError('%s가 일반 장수 및 빙의 불가 장수에 모두 있습니다!'%name)
        for name in names3:
            if name in names2:
                raise RuntimeError('%s가 확장 장수 및 빙의 불가 장수에 모두 있습니다!'%name)

        fp.write(',\n    "general_neutral":[\n        ')
        fp.write(',\n        '.join([json.dumps(general, ensure_ascii=False) for general in generalNeutralList]))
        fp.write('\n    ]')

    fp.write('\n}')