# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.

# standard python modules
import os
import glob
import shutil
import shlex
import gettext
__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

# Inary Modules
import inary.context as ctx

# ActionsAPI Modules
import inary.actionsapi
import inary.actionsapi.get as get
from inary.actionsapi.shelltools import *
from inary.actionsapi.inarytools import dodoc, dodir, domove, dosym, insinto, removeDir


WorkDir = "{0}-{1.split('_')[-1]}".format(get.srcNAME(), get.srcVERSION())

class CompileError(inary.actionsapi.Error):
    def __init__(self, value=''):
        inary.actionsapi.Error.__init__(self, value)
        self.value = value
        ctx.ui.error(value)

class InstallError(inary.actionsapi.Error):
    def __init__(self, value=''):
        inary.actionsapi.Error.__init__(self, value)
        self.value = value
        ctx.ui.error(value)

class RunTimeError(inary.actionsapi.Error):
    def __init__(self, value=''):
        inary.actionsapi.Error.__init__(self, value)
        self.value = value
        ctx.ui.error(value)

def compile(parameters = ''):
    '''compiling texlive packages'''

    # Move sources according to tplobj files
    if moveSources():
        raise CompileError(_('Moving source files failed'))
    # Generate config files
    if generateConfigFiles():
        raise CompileError(_('Generate config files failed'))
    # Build format files
    if buildFormatFiles():
        raise CompileError(_('Building format files failed'))

def install(parameters = ''):
    '''Installing texlive packages'''

    # Create symlinks from format to engines
    if createSymlinksFormat2Engines():
        raise InstallError(_('Creating symlinks from format to engines failed'))

    # Installing docs
    if installDocFiles():
        raise InstallError(_('Installing docs failed'))

    # Installing texmf, texmf-dist, tlpkg, texmf-var
    if installTexmfFiles():
        raise InstallError(_('Installing texmf files failed'))

    # Installing config files
    if installConfigFiles():
        raise InstallError(_('Installing config files failed'))

    # Handle config files
    if handleConfigFiles():
        raise Installing(_('Handle config files failed'))

def createSymlinksFormat2Engines():
    '''Create symlinks from format to engines'''
    for formatfile in ls("{}/texmf/fmtutil/format*.cnf".format(get.curDIR())):
        symfile = open(formatfile, "r")
        for line in symfile.readlines():
            if not line.startswith("#"):
                symbin = line.split(None)
                if "cont-" in symbin[0] or "metafun" in symbin[0] or "mptopdf" in symbin[0]:
                     ctx.ui.info(_('Symlink {} skipped (special case)').format(symbin[0]))
                elif "mf" in symbin[0]:
                    ctx.ui.info(_('Symlink {0[0]} -> {0[1]} skipped (texlive-core takes care of it.').format(symbin))
                else:
                    if symbin[0] == symbin[1]:
                        ctx.ui.info(_('Symlink {0[0]} -> {0[1]} skipped.').format(symbin))
                    elif can_access_file("{0}/usr/bin/{1}".format(get.installDIR(), symbin[0])):
                        ctx.ui.info(_('Symlink {} skipped (file exists.)').format(symbin[0]))
                    else:
                        ctx.ui.info(_('Making symlink from {0[0]} to {0[1]}').format(symbin))
                        dodir("/usr/bin")
                        sym(symbin[1], "{0}/usr/bin/{1}".format(get.installDIR(), symbin[0]))
        symfile.close()

def installDocFiles():
    '''Installing docs'''
    if "documentation" in get.srcNAME():
        if os.path.isdir("{}/texmf-doc".format(get.curDIR())):
            copytree("texmf-doc", "{}/usr/share/texmf-doc".format(get.installDIR()))
    else:
        for removedir in ["texmf", "texmf-dist"]:
            if os.path.isdir("{0}/{1}/doc/".format(get.curDIR(), removedir)):
                shutil.rmtree("{0}/{1}/doc".format(get.curDIR(),removedir))

def installTexmfFiles():
    '''Installing texmf, texmf-dist, tlpkg, texmf-var'''
    for installdoc in ["texmf", "texmf-dist", "tlpkg", "texmf-var"]:
        if os.path.isdir("{0}/{1}".format(get.curDIR(), installdoc)):
            if not installdoc == "texmf-var":
                shutil.copytree(installdoc, "{0}/usr/share/{1}".format(get.installDIR(),installdoc))
            else:
                copytree(installdoc, "{}/var/lib/texmf".format(get.installDIR()))

def installConfigFiles():
    '''Installing config files'''
    if can_access_file("{0}/{1}.cfg".format(get.curDIR(), get.srcNAME())):
        insinto("/etc/texmf/updmap.d", "{0}/{1}.cfg".format(get.curDIR(), get.srcNAME()))

    if can_access_file("{0}/{1}.config.ps".format(get.curDIR(), get.srcNAME())):
        insinto("/etc/texmf/dvips.d", "{0}/{1}.config.ps".format(get.curDIR(), get.srcNAME()))

    if can_access_file("{0}/{1}.config".format(get.curDIR(), get.srcNAME())):
        insinto("/etc/texmf/dvipdfm/config", "{0}/{1}.config".format(get.curDIR(), get.srcNAME()))

    if can_access_file("{0}/language/{1}.def.config".format(get.curDIR(), get.srcNAME())):
        insinto("/etc/texmf/language.def.d", "{0}/language.{1}.def".format(get.curDIR(), get.srcNAME()))

    if can_access_file("{0}/language.{1}.dat".format(get.curDIR(), get.srcNAME())):
        insinto("/etc/texmf/language.dat.d", "{0}/language.{1}.dat".format(get.curDIR(), get.srcNAME()))

def handleConfigFiles():
    '''Handling config files'''
    for root, dirs,files in os.walk("{}/usr/share/texmf".format(get.installDIR())):
        if not ("config" in root or "doc" in root):
            for configFile in files:
                if configFile.endswith(("cfg", "cnf")):
                    dirname = root.split("/")[-1]
                    if not os.path.isdir("{0}/etc/texmf/{1}.d".format(get.installDIR(),dirname)):
                        ctx.ui.info(_('Creating /etc/texmf/{}.d').format(dirname))
                        dodir("/etc/texmf/{}.d".format(dirname))
                    ctx.ui.info(_('Moving (and symlinking) /usr/share/texmf/{0} to /etc/texmf/{1}.d').format(configFile,dirname))
                    domove("/usr/share/texmf/{0}/{1}".format(dirname,configFile), "/etc/texmf/{}.d".format(dirname))
                    dosym("/etc/texmf/{0}.d/{1}".format(dirname, configFile), "/usr/share/texmf/{0}/{1}".format(dirname, configFile))

def addFormat(parameters):
    '''Add format files'''
    if not os.path.isdir("{}/texmf/fmtutil/".format(get.curDIR())):
        makedirs("{}/texmf/fmtutil/".format(get.curDIR()))
    if not os.path.isfile("{0}/texmf/fmtutil/format.{1}.cnf".format(get.curDIR(), get.srcNAME())):
        cnf_file = open("{0}/texmf/fmtutil/format.{1}.cnf".format(get.curDIR(), get.srcNAME()), "w")
        cnf_file.write("# Generated for {} by actionsapi/texlivemodules.py\n".format(get.srcNAME()))
        cnf_file.close()

    # TODO: Use regex for code simplification
    parameters = " ".join(parameters.split())   # Removing white-space characters
    parameters = shlex.split(parameters)      # Split parameters until the value "option"
    para_dict = {}
    for option in parameters:
        pair = option.strip()                   # Remove whitespaces before "options" value
        pair = pair.split("=",1)                # The value "options" may have multiple "=", thus split just one time
        if len(pair) == 2:                      # The list may contain values that are not pair
            para_dict[pair[0]] = pair[1]
            if pair[0] == "patterns" and pair[1] == '':
                para_dict["patterns"] = '-'     # Specified in the texlive-module.eclass
            elif not pair[0] == 'patterns':
                para_dict["patterns"] = '-'

    cnf_file = open('{0}/texmf/fmtutil/format.{1}.cnf'.format(get.curDIR(), get.srcNAME()), 'a')
    cnf_file.write('{0[name]}\t{0[engine]}\t{0[patterns]}\t{0[options]}\n'.format(para_dict))
    cnf_file.close()

def moveSources():
    reloc = "texmf-dist"

    for tlpobjfile in os.listdir("tlpkg/tlpobj/"):
        jobsfile=open("tlpkg/tlpobj/{}".format(tlpobjfile), "r")
        for line in jobsfile.readlines():
            if "RELOC" in line:
                path = line.split("/", 1)[-1]
                path = path.strip()
                filename = path.split("/", -1)
                dirname = os.path.dirname(path)
                if not os.path.isdir("{0}/{1}".format(reloc,dirname)):
                    os.system("mkdir -p {0}/{1}".format(reloc,dirname))
                shutil.move("{}".format(path) , "{0}/{1}".format(reloc,dirname))

def buildFormatFiles():
    '''Build format files'''
    if os.path.isdir("{}/texmf/fmtutil/".format(get.curDIR())):
        for formatfile in ls("{}/texmf/fmtutil/format*.cnf".format(get.curDIR())):
            makedirs("{}/texmf-var/web2c/".format(get.curDIR()))
            ctx.ui.info(_('Building format file {}').format(formatfile))
            export("TEXMFHOME", "{0}/texmf:/{0}texmf-dist:{0}/texmf-var".format(get.curDIR()))
            export("VARTEXFONTS", "fonts")
            system("env -u TEXINPUTS fmtutil --cnffile {} --fmtdir texmf-var/web2c --all".format(formatfile))

def addLanguageDat(parameter):
    '''Create language.*.dat files'''
    parameter = parameter.split()
    para_dict={}
    for option in parameter:
        pair = option.split("=")
        if len(pair) == 2: #That's just a caution, the pair should have two items, not more not less
            para_dict[pair[0]] = pair[1]

    language_dat = open('{0}/language.{1}.dat'.format(get.curDIR(), get.srcNAME())  , 'a')
    language_dat.write('{0[name]}\t{0[file]}\n"'.format(para_dict))
    language_dat.close()

    if "synonyms" in para_dict:
        language_dat = open('{0}/language.{1}.dat'.format(get.curDIR(),get.srcNAME())  , 'a')
        language_dat.write("={}\n".format(para_dict["synonyms"]))
        language_dat.close()

def addLanguageDef(parameter):
    '''Create language.*.def files'''
    parameter = parameter.split()
    para_dict={}
    for option in parameter:
        pair = option.split("=")
        if len(pair) == 2: #That's just a caution, the pair should have two items, not more not less
            para_dict[pair[0]] = pair[1]

    if "lefthyphenmin" in para_dict and not para_dict["lefthyphenmin"]:
        para_dict["lefthyphenmin"] = "2"
    if "righthyphenmin" in para_dict and not para_dict["righthyphenmin"]:
        para_dict["righthyphenmin"] = "3"

    language_def = open('{0}/language.{1}.def'.format(get.curDIR(),get.srcNAME())  , 'a')
    language_def.write("\\addlanguage{%s}{%s}{}{%s}{%s}\n" % (para_dict["name"], para_dict["file"],  para_dict["lefthyphenmin"],  para_dict["righthyphenmin"]))
    language_def.close()

    if "synonyms" in para_dict:
        language_def = open('{0}/language.{1}.def'.format(get.curDIR(),get.srcNAME())  , 'a')
        language_def.write("\\addlanguage{%s}{%s}{}{%s}{%s}\n" % (para_dict["synonyms"], para_dict["file"],  para_dict["lefthyphenmin"],  para_dict["righthyphenmin"]))
        language_def.close()

def generateConfigFiles():
    '''Generate config files'''
    for tlpobjfile in ls("{}/tlpkg/tlpobj/*".format(get.curDIR())):
        jobsfile=open(tlpobjfile, "r")
        for line in jobsfile.readlines():
            splitline = line.split(" ", 2)
            if splitline[0] == "execute":
                command = splitline[1]
                parameter = splitline[2].strip()
                if command == "addMap":
                    echo("{0}/{1}.cfg".format(get.curDIR, get.srcNAME()), "Map {}".format(parameter))
                    ctx.ui.info(_('Map {0} is added to {1}/{2}.cfg').format(parameter, get.curDIR(), get.srcNAME()))
                elif command == "addMixedMap":
                    echo("{0}/{1}.cfg".format(get.curDIR(), get.srcNAME()), "MixedMap {}".format(parameter))
                    ctx.ui.info(_('MixedMap {0} is added to {1}/{2}.cfg').format(parameter, get.curDIR(), get.srcNAME()))
                elif command == "addDvipsMap":
                    echo("{0}/{1}-config.ps".format(get.curDIR(), get.srcNAME()), "p +{}".format(parameter))
                    ctx.ui.info(_('p +{0} is added to {1}/{2}-config.ps').format(parameter, get.curDIR(), get.srcNAME()))
                elif command == "addDvipdfmMap":
                    echo("{0}/{1}-config".format(get.curDIR(), get.srcNAME()), "f {}".format(parameter))
                    ctx.ui.info(_('f {0} is added to {1}/{2}-config').format(parameter, get.curDIR(), get.srcNAME()))
                elif command == "AddHyphen":
                    addLanguageDat(parameter)
                    addLanguageDef(parameter)
                elif command == "AddFormat":
                    addFormat(parameter)
                elif command == "BuildFormat":
                    ctx.ui.info(_('Language file  {}  already generated.').format(parameter))
                elif command == "BuildLanguageDat":
                    ctx.ui.info(_('No rule to proccess {}. Please file a bug.').format(command))
        jobsfile.close()

