#!/usr/bin/env python3

# == Rapid Develop Macros in LibreOffice ==

# ~ This file is part of ZAZ.

# ~ ZAZ 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 3 of the License, or
# ~ (at your option) any later version.

# ~ ZAZ is distributed in the hope that it will be useful,
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# ~ GNU General Public License for more details.

# ~ You should have received a copy of the GNU General Public License
# ~ along with ZAZ.  If not, see <https://www.gnu.org/licenses/>.

import argparse
import os
import sys
from pathlib import Path
from shutil import copyfile
from subprocess import call
import zipfile

from conf import (
    DATA,
    DIRS,
    EXTENSION,
    FILES,
    INFO,
    PATHS,
    TYPE_EXTENSION,
    USE_LOCALES,
    log)


def _exists(path):
    return os.path.exists(path)


def _join(*paths):
    return os.path.join(*paths)


def _mkdir(path):
    return Path(path).mkdir(parents=True, exist_ok=True)


def _save(path, data):
    with open(path, 'w') as f:
        f.write(data)
    return


def _compress_oxt():
    log.info('Compress OXT extension...')

    path = DIRS['files']
    if not _exists(path):
        _mkdir(path)

    path_oxt = _join(path, FILES['oxt'])

    z = zipfile.ZipFile(path_oxt, 'w', compression=zipfile.ZIP_DEFLATED)
    root_len = len(os.path.abspath(DIRS['source']))
    for root, dirs, files in os.walk(DIRS['source']):
        relative = os.path.abspath(root)[root_len:]
        for f in files:
            fullpath = _join(root, f)
            file_name = _join(relative, f)
            if file_name == FILES['idl']:
                continue
            z.write(fullpath, file_name, zipfile.ZIP_DEFLATED)
    z.close()

    if DATA['update']:
        path_xml = _join(path, FILES['update'])
        _save(path_xml, DATA['update'])

    log.info('Extension OXT created sucesfully...')
    return


def _install_and_test():
    path_oxt = (_join(DIRS['files'], FILES['oxt']),)
    call(PATHS['install'] + path_oxt)
    log.info('Install extension sucesfully...')
    log.info('Start LibreOffice...')
    call(PATHS['soffice'])
    return


def _validate_new():
    path_source = DIRS['source']
    if not _exists(path_source):
        return True

    msg = f'Path: {path_source}, exists, delete first'
    log.error(msg)
    return False


def _create_new_directories():
    path_source = DIRS['source']
    _mkdir(path_source)
    path = _join(path_source, DIRS['meta'])
    _mkdir(path)
    path = _join(path_source, DIRS['description'])
    _mkdir(path)
    path = _join(path_source, DIRS['images'])
    _mkdir(path)
    path = _join(path_source, DIRS['registration'])
    _mkdir(path)
    path = _join(path_source, DIRS['office'])
    _mkdir(path)

    if FILES['easymacro'] or DIRS['pythonpath']:
        path = _join(path_source, 'pythonpath')
        _mkdir(path)

    path = DIRS['files']
    if not _exists(path):
        _mkdir(path)

    msg = 'Created directories...'
    log.info(msg)
    return


def _create_new_files():
    path_source = DIRS['source']

    for k, v in INFO.items():
        file_name = f'license_{k}.txt'
        path = _join(path_source, DIRS['registration'], file_name)
        _save(path, v['license'])

    if TYPE_EXTENSION > 1:
        path = _join(path_source, FILES['idl'])
        _save(path, DATA['idl'])

    path = _join(path_source, FILES['py'])
    _save(path, DATA['py'])


    msg = 'Created files...'
    log.info(msg)
    return


def _validate_update():
    if TYPE_EXTENSION == 1:
        return True

    if not _exists(PATHS['idlc']):
        msg = 'Binary: "idlc" not found'
        log.error(msg)
        return False

    if not _exists(PATHS['include']):
        msg = 'Directory: "include" not found'
        log.error(msg)
        return False

    if not _exists(PATHS['regmerge']):
        msg = 'Binary: "regmerge" not found'
        log.error(msg)
        return False

    path = _join(DIRS['source'], FILES['idl'])
    if not _exists(path):
        msg = f'File: "{FILES["idl"]}" not found'
        log.error(msg)
        return False

    return True


def _compile_idl():
    if TYPE_EXTENSION == 1:
        return

    log.info('Compilate IDL...')
    path_rdb = _join(DIRS['source'], FILES['rdb'])
    path_urd = _join(DIRS['source'], FILES['urd'])

    path = _join(DIRS['source'], FILES['idl'])
    call([PATHS['idlc'], '-I', PATHS['include'], path])
    call([PATHS['regmerge'], path_rdb, '/UCR',  path_urd])
    os.remove(path_urd)

    log.info('Compilate IDL sucesfully...')
    return


def _update_files():
    path_source = DIRS['source']

    for k, v in INFO.items():
        file_name = FILES['ext_desc'].format(k)
        path = _join(path_source, DIRS['description'], file_name)
        _save(path, v['description'])

    path_logo = EXTENSION['icon'][0]
    if _exists(path_logo):
        file_name = EXTENSION['icon'][1]
        path = _join(path_source, DIRS['images'], file_name)
        copyfile(path_logo, path)

    files = os.listdir(DIRS['images'])
    for f in files:
        if f[-3:].lower() == 'bmp':
            source = _join(DIRS['images'], f)
            target = _join(path_source, DIRS['images'], f)
            copyfile(source, target)

    if FILES['easymacro']:
        source = 'easymacro.py'
        target = _join(path_source, 'pythonpath', source)
        copyfile(source, target)

    path = _join(path_source, DIRS['meta'], FILES['manifest'])
    _save(path, DATA['manifest'])

    path = _join(path_source, DIRS['office'])
    _mkdir(path)
    path = _join(path_source, DIRS['office'], FILES['shortcut'])
    _save(path, DATA['shortcut'])

    path = _join(path_source, FILES['addons'])
    _save(path, DATA['addons'])

    path = _join(path_source, FILES['description'])
    _save(path, DATA['description'])

    if TYPE_EXTENSION == 3:
        path = _join(path_source, FILES['addin'])
        _save(path, DATA['addin'])

    if USE_LOCALES:
        msg = "Don't forget generate DOMAIN.pot for locales"
        log.info(msg)
        for lang in EXTENSION['languages']:
            path = _join(path_source, DIRS['locales'], lang, 'LC_MESSAGES')
            Path(path).mkdir(parents=True, exist_ok=True)

    _compile_idl()
    return


def _new():
    if not _validate_new():
        return

    _create_new_directories()
    _create_new_files()
    _update_files()

    msg = f"New extension: {EXTENSION['name']} make sucesfully...\n"
    msg += '\tNow, you can install and test: zaz.py -i'
    log.info(msg)
    return


def main(args):
    if args.new:
        _new()
        return

    if not _validate_update():
        return

    _update_files()
    _compress_oxt()

    if args.install:
        _install_and_test()

    log.info('Extension make sucesfully...')
    return


def _process_command_line_arguments():
    parser = argparse.ArgumentParser(
        description='Make LibreOffice extensions')
    parser.add_argument('-i', '--install', dest='install', action='store_true',
        default=False, required=False)
    parser.add_argument('-n', '--new', dest='new', action='store_true',
        default=False, required=False)
    return parser.parse_args()


if __name__ == '__main__':
    args = _process_command_line_arguments()
    main(args)

