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

import os
import sys
import time
import types
import re

import xmir_base
import ssh2
from gateway import *


class www_lmo():
  fn_local = None
  fn_remote = None
  data = None
  out = []
  
  def __init__(w, fn_local = None, fn_remote = None):
    w.fn_local = fn_local
    w.fn_remote = fn_remote
    w.data = None
    w.out = []    

  def load_file(w):
    with open(w.fn_local, "r", encoding="utf-8") as file:
      w.data = file.read()
  
  def parse(w):
    if not w.data:
      w.load_file()
    p = re.compile(r'[^%][>]([^><]*?[\u4e00-\u9fff][^><]*?)[<][^%]')
    w.parse1(p)
    p = re.compile(r'[\']([^><\n\']*?[\u4e00-\u9fff][^><\n\']*?)[\']')
    w.parse1(p)
    p = re.compile(r'["]([^><\n"]*?[\u4e00-\u9fff][^><\n"]*?)["]')
    w.parse1(p)

  def parse1(w, template):
    for m in template.finditer(w.data):
      txt = m.group()
      if txt.find('<%') > 0 or txt.find('%>') > 0:
        continue
      if txt.find('// ') > 0:  # skip comments
        continue
      if txt.find('if ') > 0:  # skip code
        continue
      if txt.find('{') > 0:    # skip code
        continue
      if txt.find(' = ') > 0:  # skip code
        continue
      b = m.start()
      t1 = m.start(1)
      t2 = m.end(1)
      e = m.end()
      #print(b, t1, t2, e)
      prefix = w.data[b:t1]
      string = w.data[t1:t2]
      postfix = w.data[t2:e]
      if len(prefix) == 2 and prefix[1] == '>':
        prefix = prefix[1]
        txt = txt[1:]
      if len(postfix) == 2 and postfix[0] == '<':
        postfix = postfix[0]
        txt = txt[:-1]
      #print('"{}" "{}" "{}"'.format(prefix, string, postfix))
      s = string.strip()
      if s == string:
        out = prefix + '<%:' + string + '%>' + postfix
        msg = string
      else:
        p = string.find(s)
        if p < 0:
          continue  # fixme
        out = prefix + string[:p] + '<%:' + s + '%>' + string[p+len(s):] + postfix
        msg = s
      #print(b, out)
      # check for dup
      dup = 0
      for i, v in enumerate(w.out):
        if v.txt_orig == txt:
          dup = 1
          break
      if dup == 0:
        v = types.SimpleNamespace()
        v.pos = b
        v.txt_orig = txt
        v.txt_new = out
        v.sed = ""
        v.msg = msg
        w.out.append(v)

  def sed_escape(w, txt):
    txt = txt.replace('\\', '\\\\')
    txt = txt.replace('\n', r'\n')
    txt = txt.replace('\r', r'\r')
    txt = txt.replace('\t', r'\t')
    txt = txt.replace("'", r"'\''")
    txt = txt.replace('[', r'\[')
    txt = txt.replace(']', r'\]')
    txt = txt.replace('$', r'\$')
    txt = txt.replace('*', r'\*')
    txt = txt.replace('.', r'\.')
    txt = txt.replace('$', r'\$')
    txt = txt.replace('^', r'\^')
    txt = txt.replace('/', r'\/')
    return txt

  def gen_sed(w):
    for i, v in enumerate(w.out):
      #print(v.pos, v.txt_new)
      orig = w.sed_escape(v.txt_orig)
      new  = w.sed_escape(v.txt_new)
      prefix = ''
      if v.txt_orig.find('\n') > 0:
        prefix = ':a;N;$!ba;'  # see: https://stackoverflow.com/questions/1251999/how-can-i-replace-each-newline-n-with-a-space-using-sed
      v.sed = "sed -i '{}s/{}/{}/g' {}".format(prefix, orig, new, w.fn_remote) 


gw = Gateway()

fn_dir      = 'data/'
fn_local    = 'data/lang_patch.sh'
fn_remote   = '/tmp/lang_patch.sh'
fn_local_i  = 'data/lang_install.sh'
fn_remote_i = '/tmp/lang_install.sh'
fn_local_u  = 'data/lang_uninstall.sh'
fn_remote_u = '/tmp/lang_uninstall.sh'
fn_www_local  = f'tmp/lang_patch_www.sh'
fn_www_remote = '/tmp/lang_patch_www.sh'

os.makedirs('tmp', exist_ok = True)

full_install = False
action = 'install'
if len(sys.argv) > 1:
  if sys.argv[1] == 'full':
    full_install = True
  if sys.argv[1].startswith('u') or sys.argv[1].startswith('r'):
    action = 'uninstall'

if action == 'install':
  gw.upload(fn_local, fn_remote)
  gw.upload(fn_local_i, fn_remote_i)

gw.upload(fn_local_u, fn_remote_u)

if action == 'install':
  patch_installed = 0
  fn = 'tmp/lang_patch.log'
  if os.path.exists(fn):
    os.remove(fn)
  try:
    gw.download('/tmp/lang_patch.log', fn, verbose = 0)
  except ssh2.exceptions.SCPProtocolError:
    patch_installed = 0
  txt = ''
  if os.path.exists(fn):
    with open(fn, 'r') as file:
      txt = file.read()
  if txt:
    patch_installed = 2 if 'www_patch' in txt else 1
  if patch_installed >= 2:
    die("Full lang patch already installed!")
  #if patch_installed:
  #  print("Uninstall lang_patch...")
  #  gw.run_cmd(f"chmod +x {fn_remote_u} ; {fn_remote_u}")

if action == 'install':
  import po2lmo
  for filename in [fn for fn in os.listdir(fn_dir) if fn.split(".")[-1] in ['po']]:
    fname = fn_dir + filename
    print('Convert file "{}" to LMO ...'.format(fname))
    lmo = po2lmo.Lmo()
    lmo.skip_dup = True
    lmo.load_from_text(fname)
    lmo_fname = os.path.splitext(filename)[0] + '.lmo'
    lmo.save_to_bin(fn_dir + lmo_fname)
    gw.upload(fn_dir + lmo_fname, '/tmp/' + lmo_fname)

if action == 'install' and full_install:
  dn_www = "tmp/www"
  os.makedirs(dn_www, exist_ok = True)
  wwwlst = [ "/usr/lib/lua/luci/view/web/index.htm",
             "/usr/lib/lua/luci/view/web/apindex.htm",
             "/usr/lib/lua/luci/view/web/inc/g.js.htm",
             "/usr/lib/lua/luci/view/web/inc/header.htm",
             "/usr/lib/lua/luci/view/web/inc/sysinfo.htm",
             "/usr/lib/lua/luci/view/web/inc/wanCheck.js.htm",
             "/usr/lib/lua/luci/view/web/setting/iptv.htm",
           ]  
  www = []
  for i, www_remote in enumerate(wwwlst):
    www_local = dn_www + '/' + www_remote.replace('/', '_')
    try:
      gw.download(www_remote, www_local, verbose = 0)
    except ssh2.exceptions.SCPProtocolError:
      print('WARN: file "{}" not found'.format(www_remote))
      continue
    w = www_lmo(www_local, www_remote)
    www.append(w)
  if os.path.exists(fn_www_local):
    os.remove(fn_www_local)  
  file = open(fn_www_local, "wt", encoding='UTF-8', newline = "\n")
  file.write('#!/bin/sh\n')
  for i, w in enumerate(www):
    #print("===== FILE:", w.fn_remote)
    w.parse()
    w.gen_sed()
    file.write('# ======= FILE: {} ======= \n'.format(w.fn_remote))
    for i, v in enumerate(w.out):
      if v.sed:
        file.write(v.sed + '\n')
  file.close()
  gw.upload(fn_www_local, fn_www_remote)
  
print("All files uploaded!")

print("Run scripts...")
run_script = fn_remote_i if action == 'install' else fn_remote_u
gw.run_cmd(f"chmod +x {run_script} ; {run_script}", timeout = 17)

time.sleep(1.5)

gw.run_cmd(f"rm -f {fn_remote} ; rm -f {fn_remote_i} ; rm -f {fn_remote_u}")
if full_install:
    gw.run_cmd(f"rm -f {fn_www_remote}")

prefix = '' if action == 'install' else 'un'
print(f"Ready! The language files are {prefix}installed.")
