import re
import os
import json
import html
import urllib.parse
import platform
import time
import hashlib
import subprocess
############################################################
############################################################
convert_all_md_files_to_html = True # 如果设定为False, 不会转换落单的md 
changeGGbh5file = True # 如果设定为True, 会修改ggb的网页文件, 可以自动调整路径, 以便正常显示
### First line identification, 
author = 'zbzhen'  # any str
firstlinesite = "https://kz16.top" # any str

### js or css files
is_onlinesite = False  # 如果设定为True输出为在线html, ggb的在线支持需要在md文件中额外设置在线路径(共三处)
onlinesite = "https://kz16.top/"
logo =  "kz16logo.svg"   
css =  "css/kz16.css"
katexcss =  "css/katex.css"
mermaidjs = "js/mermaid.min.js"
search_local_dir = "js/" 
search_path = search_local_dir + "search.js"
### upload .html files to remote server  # 一键上传到服务器需要设定为密钥登陆
upload = False 
usr = 'root'
ip = 'xxx.xxx.xxx.xxx'
remotepath = '/var/www/html'
constrain_https = False # 强制页面转换为https 
search = True # 这里统一为本地相对路径, 有需要的话在代码中可以手动改变
############################################################
############################################################

mume = './mume '
ss = '/'
if platform.system().lower()== 'windows':
    mume = '.\mume.exe '
    ss = '\\'

sshremote = 'ssh ' + usr + '@' + ip
sshfile = usr + '@' + ip + ':' + remotepath
firstline = '<!-- by ' + author + ', ' + firstlinesite + ' -->\n'

path = os.getcwd()
lenpath = len(path)
############################################################
############################################################
def gettx(cdir, description, md5, site):
    searchjson=''
    searchdiv = ''
    if search == True:
        searchjson='<script src="' + site + search_path + '"></script>'
        searchdiv = """
            <div class="kz16bar">
                <input type="text" id="search" onkeyup="searchJSON()"  placeholder="">
            </div>
            <div id="output"></div>
            <script>
            function search(searchInput) {
                var outputDiv = document.getElementById("output");
                outputDiv.innerHTML = "";
                for(let i = 0; i< out['articles'].length; i++) {
                    if (out['articles'][i]['title'].toLowerCase().includes(searchInput)) {
                        outputDiv.innerHTML += "<li><a href='"+ out['articles'][i]['url'] + "' title='" + out['articles'][i]['title'] + "'>" + out['articles'][i]['mytitle']  + "</a></li>";
                    }
                }
            }
            var input = document.getElementById("search").value.trim().toLowerCase();
            """ \
            + 'var defaultinput ="' + cdir + '";' + \
            """
            if(!input){
                search(defaultinput);
            }
            function searchJSON() {
                var searchInput = document.getElementById("search").value.trim().toLowerCase();
                if(searchInput){
                    search(searchInput);
                    return
                }
                search(defaultinput);
            }
            </script></div>
        """
    https = ''
    if constrain_https == True:
        https = '<script type="text/javascript">\n\
                var loc = location.href.split(":");\n\
                if(loc[0]=="http"){\n\
                    location.href="https:"+loc[1];\n\
                }\n\
                </script>\n'

    tx0 = firstline  + md5  +'<!DOCTYPE html>\n'\
        +'<html> <head>\n'

    tx1 = '        <meta charset="utf-8">\n\
            <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>\n\
            <meta name="description" content="' + description + '"> \n\
            <link rel="shortcut icon" href="'+ site + logo +'" />\n\
            <link rel="stylesheet" href="'+ site +css+'"/>\n'\
        + https + searchjson + '</head>\n\n\n\
        <body class="kz16">\n\
            <div class="mume markdown-preview">\n\
            <div class="mylefttoc">\n'
    
    tx2 = '        </div><div class="myrighttoc">\n' \
            +searchdiv+ '\n<div class="kz16__right"><div class="kz16__html">\n'


    mermaindjs = '<script type="text/javascript" src="'+ site+mermaidjs+'"></script>\n' \
        +'<script>mermaid.initialize({ startOnLoad: true });</script>\n'

            
    txendl = '<link rel="stylesheet" href="'+ site+katexcss+'"/></div></div></body></html>'
    return tx0, tx1, tx2, mermaindjs, txendl



def get_start_num(lines):
    for k, line in enumerate(lines[250:630]):
        hn = re.findall(r'</h(\d{1})>', line[-6:])
        if hn != []:
            snsub = re.search(r'<h', line).span()[0]
            return k+250, snsub

def get_end_num(lines):
    t = -1
    for k in range(-1,-100,-1): 
        if re.findall(r'</div>', lines[k]) != []:
            t = k
            break
    m = -1
    Mline = len(lines)
    for k in range(t, 1-Mline, -1): 
        if  re.findall(r'<div class="md-sidebar-toc">', lines[k][:40]) != []:
            m = k
            break
    if m == -1:
        return t 
    return m  


def get_title_and_toc(lines, sn, snsub):
    newlines = lines[sn:]
    newlines[0] = lines[sn][snsub:]
    hnum = []
    index = []
    for k, line in enumerate(newlines):
        hn = re.findall(r'</h(\d{1})>', line[-6:])
        if hn != []:
            hn = int(hn[0])
            hnum += [hn]
            index += [k]

    a0 = '<a href="#'
    a1 = '">'
    a2 = '</a>'
    tmp = []
    title = []
    t = 0
    allhid=''
    tss=''
    for ind in index:
        line = newlines[ind]
        hid = re.findall(r'id="(.*?)"', line)
        htt = re.findall(r'">(.*?)</h', line)
        if hid == []:
            htt = re.findall(r'<h.*?>(.*?)</h', line)[-1]
            hid = htt
            if t==0:
                title = htt
            old = '>' +  htt
            new = ' id="' + hid + '">' + htt
            tmpline = ''.join(lines[ind+sn]).replace(old, new)
            lines[ind+sn] =  tmpline
            tss = htt
            t += 1
        else:
            hid = hid[-1]
            htt = htt[-1]
            tss = hid
        tss = html.unescape(urllib.parse.unquote(tss))
        allhid += tss+', '
        tmp += [a0 + hid + a1 + htt + a2]
    lefts = ['<li>', '<ul><li>', '<ul><li><ul><li>', '<ul><li><ul><li><ul><li>']
    rights = ['</li>\n', '</li></ul></li>\n', '</li></ul></li></ul></li>\n', \
            '</li></ul></li></ul></li></ul>\n', '\n']
    hnum += [0]
    toc = ''
    for i in range(len(hnum)-1):
        t1 = hnum[i] - hnum[i-1]
        if t1 <= 0:
            t1 = 0
        t2 = hnum[i] - hnum[i+1]
        toc += lefts[t1] + tmp[i] + rights[t2]
    if title == []:
        title = re.findall(r'<h.*?>(.*?)</h', newlines[0])[-1]
    return title, toc, lines, allhid

class Num:
    all_file_nums = 0
    modified_file_nums = 0
    search_file_nums = 0
    pass


def make(filename, filelen, num, site):
    url= filename
    if is_onlinesite:
        url= site + filename[lenpath:]
    url = url.replace('\\', '/')
    cdir = filename.split(ss)[-2]
    existenceMermaid = False
    print(filename)
    num.all_file_nums += 1
    with open(filename,'r', encoding='UTF-8') as f:
        lines = f.readlines()
        if len(lines)<10:
            print('search: no')
            return 
        if lines[0] != firstline and lines[-1] != firstline:
            print('search: no')
            return
        if lines[0] == firstline:
            if lines[7][:36]=='            <meta name="description"':
                num.search_file_nums += 1
                ttt = cdir + ', ' + urllib.parse.unquote(lines[7][46:-4])
                print('search: yes')
                return {"mytitle": html.unescape(lines[4][7:-9]), "title":ttt,  "url":url}
            print('search: no')
            return
        for line in lines[5:15]:
            mjs = re.findall(r'mermaid.min.js" charset="UTF-8"></script>', line)
            mjs2 = re.findall(r'mermaid.min.js"></script>', line[-30:])
            if (mjs != []) or (mjs2 != []):
                existenceMermaid = True
                break

    
    
    num.search_file_nums += 1
    num.modified_file_nums += 1

    old = 'class="mord mathnormal'
    new = 'class="mord mathdefault'

    sn, snsub = get_start_num(lines)
    en = get_end_num(lines)
    title, toc, lines, allhid = get_title_and_toc(lines, sn, snsub)

    mdfile = filename[:-4]+'md'

    md5 = ''
    mdfinfo = ''
    if os.path.exists(mdfile):
        with open(mdfile, 'r', encoding='utf-8') as fm:
            mdct = fm.read()
            md5 = hashlib.md5(mdct.encode('utf-8')).hexdigest()
        md5 = '<!-- ' + md5 + ' -->\n'
        modify_time = time.ctime(os.path.getmtime(mdfile))
        mdfinfo = 'Author : ' + author+ ",&nbsp; &nbsp; &nbsp; &nbsp; Modified : " + modify_time
        mdfinfo = '<p style="color:#939393;">' + mdfinfo + '</p>\n'

    tx0, tx1, tx2, mermaindjs, txendl = gettx(cdir, allhid, md5, site)
    with open(filename,'w', encoding='UTF-8') as f:
        f.writelines(tx0)
        newline = '<title>' +title+'</title>\n'
        
        f.writelines(newline)
        f.writelines(tx1)
        f.writelines(toc)
        f.writelines(tx2)
        newline = '<h1 id ="'+title+ '">' + title + '</h1>\n'
        f.writelines(newline)
        f.writelines(mdfinfo)
        newline = ''.join(lines[sn+1:en]).replace(old,new)
        f.writelines(newline)
        if existenceMermaid:
            f.writelines(mermaindjs)
        f.writelines(txendl)
        print('----- modified successfully')

    if upload:
        di = "'" + remotepath + filename[lenpath:-filelen] + "'"

        cmm = sshremote+' "[ -d '+di+' ] && echo ok; mkdir -p ' + di
        cmm = cmm.replace('\\', '/')
        cmm += '; exit; "  '
        cmd = 'scp ' + filename + ' ' + sshfile + filename[lenpath:]
        print(cmd)
        subprocess.run(cmm, shell=True)
        subprocess.run(cmd, shell=True)
        # val = os.system(cmm)
        # val = os.system(cmd)
    keywords = cdir+', ' + allhid
    print('search: yes')
    return {"mytitle": html.unescape(title), "title":keywords,  "url":url}
    

def get_path_and_file_name_list(path):
    listfiles = []
    listn = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if file[-5:] == ".html" or file[-3:] == ".md":
                listfiles.append(root+ ss +file)
                listn.append(len(file))
    return listfiles, listn



def convert_md_to_html(files):
    """
    # convert md --> html
    # append txt meessage f"{firstline}" in the last line of html
    """
    for i in range(len(files)):
        if files[i][-3:] == ".md":
            htmlfile = files[i][:-3]+".html"
            mdfile =  files[i]
            line0 = ''
            line1 = ''
            lined = ''
            change = True
            if os.path.exists(htmlfile):
                with open(htmlfile, 'r', encoding='utf-8') as f:
                    lines = f.readlines()
                    if len(lines) > 1:
                        line0, line1 = lines[:2]
                        lined = lines[-1]
            elif convert_all_md_files_to_html:  
                cmd = mume + mdfile
                print(cmd)
                subprocess.run(cmd, shell=True)
                print('----- mume exe successfully')
                with open(htmlfile, 'a', encoding='utf-8') as f:
                    f.write('\n\n'+firstline)
                continue
            else:
                change = False
            if change and (lined != firstline):
                with open(mdfile, 'r', encoding='utf-8') as fm:
                    mdct = fm.read()
                    md5 = hashlib.md5(mdct.encode('utf-8')).hexdigest()
                if (line0 != firstline) or (line0 == firstline and line1[:4] == '<!--' and line1[5:-5] != md5):
                    cmd = mume + mdfile
                    print(cmd)
                    subprocess.run(cmd, shell=True)
                    print('----- mume exe successfully')
                    with open(htmlfile, 'a', encoding='utf-8') as f:
                        f.write('\n\n'+firstline)
    return




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

files, fileslen = get_path_and_file_name_list(path)
current_dir = os.path.dirname(os.path.abspath(__file__))
current_dir_len = len(current_dir) + 1
js = json.loads(json.dumps([]))
num = Num()

convert_md_to_html(files)
dirinds = ['./', '../', '../../', '../../../', '../../../../', '../../../../../', '../../../../../../']

ttt1 = "<script>applet.setHTML5Codebase('"
ttt3 = "geogebra/5.0/web3d/'); window.onload = function() {applet.inject('ggbApplet');};</script>\n"

if is_onlinesite:
    site = onlinesite
    for i in range(len(files)):
        if files[i][-5:] == ".html":
            ds = make(files[i], fileslen[i], num, site)
            if ds != None:
                js.append(json.loads(json.dumps(ds)))
else:
    for i in range(len(files)):
        if files[i][-5:] == ".html":
            tmp = files[i][current_dir_len:]
            kk = tmp.count('/') + tmp.count('\\')
            site = dirinds[kk]
            if changeGGbh5file and site != dirinds[0]:
                with open(files[i], 'r', encoding='UTF-8') as f:
                    lines = f.readlines()
                lines1 = lines[1]
                if len(lines1) >  2000 and lines[-1] != firstline:
                    gg_old = '"./geogebra'
                    js_old = '"./js'
                    gg_new = '"' + site + 'geogebra'
                    js_new = '"' + site + 'js'
                    xx = lines1[   :250]
                    aa = lines1[250:800]
                    bb = lines1[800:-250]
                    cc = lines1[-250:]
                    aax = aa.replace(gg_old, gg_new).replace(js_old, js_new)
                    ccx = cc.replace(gg_old, gg_new).replace(js_old, js_new)
                    tttt = ttt1+ site+ ttt3
                    tttx = tttt
                    if cc[-20:] == '</div></body></html>':
                        lines[1] = xx + aax + bb + ccx
                    elif  (len(lines)>2 and lines[2] == tttt) or aa == aax:
                        tttx = ''
                    if cc[-10:] == '</script>\n': 
                        lines[1] = xx + aax + bb + ccx + tttx
                    elif cc[-23:] == '</script></body></html>':
                        lines[1] = xx + aax + bb + ccx[:-14] + '\n' + tttx + ccx[-14:]
                    with open(files[i], 'w', encoding='UTF-8') as f:
                        # f.write(''.join(lines) )
                        f.write(''.join(lines) + '\n' + firstline)
                    print("File modified: ", files[i])
            ds = make(files[i], fileslen[i], num, site)
            if ds != None:
                js.append(json.loads(json.dumps(ds)))


with open(search_path, 'w', encoding='utf-8') as f:
    f.writelines('var out = {searchString: "", articles:')
    json.dump(js, f, ensure_ascii=False, indent=4)
    f.writelines('};')

if upload:
    di = "'" + remotepath + '/' + search_local_dir + "'"
    cmm = sshremote+' "[ -d '+di+' ] && echo ok; mkdir -p ' + di
    cmm = cmm.replace('\\', '/')
    cmm += '; exit; "  '
    cmd = 'scp ' + search_path + ' ' + sshfile + '/'+ search_path
    print(cmd)
    subprocess.run(cmm, shell=True)
    subprocess.run(cmd, shell=True)

print('------------------------------------------')
print('Total html files:     ', num.all_file_nums)
print('Total searched files: ', num.search_file_nums)
print('Total modified files: ', num.modified_file_nums)