#!/c/Python27/python.exe
"""
Do './build_windows.py build' to build exe, then call
'makensis syncthing-gtk.nsis' to create installation package.
"""

import os
import pprint
import re
import shutil
import sys
from subprocess import PIPE, Popen
from tempfile import mkdtemp

from cx_Freeze import Executable, setup
from cx_Freeze.freezer import Freezer, VersionInfo
from win32verstamp import stamp

from setup import find_mos
from setup import get_version as _get_version


gnome_dll_path = "/Python27/Lib/site-packages/gnome"
build_dir = "./build/exe.win32-2.7/"

# List of dlls that cx_freeze can't detect automatically
missing_dll = [
    'libgtk-3-0.dll',
    'libgdk-3-0.dll',
    'libatk-1.0-0.dll',
    'libcairo-gobject-2.dll',
    'libgdk_pixbuf-2.0-0.dll',
    # 'libgirepository-1.0-1.dll',
    # 'libgmodule-2.0-0.dll',
    # 'libgladeui-2-6.dll',
    'libpango-1.0-0.dll',
    'libpangocairo-1.0-0.dll',
    'libpangoft2-1.0-0.dll',
    'libpangowin32-1.0-0.dll',
    'libffi-6.dll',
    # 'libgio-2.0-0.dll',
    'libharfbuzz-gobject-0.dll',
    'libharfbuzz-0.dll',
    # 'libpng16-16.dll',
    # 'libxmlxpat.dll',
    # 'libintl-8.dll',
    'librsvg-2-2.dll',
    # 'libzzz.dll',
    'libtiff-5.dll',
    'libwebp-5.dll',
    # 'libfreetype-6.dll',
    # 'libwinpthread-1.dll',
    'libepoxy-0.dll',
    'libjasper-1.dll',
    'libjpeg-8.dll',

    'gspawn-win32-helper.exe',
    'gspawn-win32-helper-console.exe',
]

# List of dlls that are exported from wrong source (or broken for
# somehow other reason
wrong_sized_dll = [
    'libcairo-gobject-2.dll',
    'libpangocairo-1.0-0.dll',
    'libfontconfig-1.dll',
    'libglib-2.0-0.dll',
    'libgobject-2.0-0.dll',
    'libgthread-2.0-0.dll',
]

# List of languages that are copied from GTK and included in installation
enabled_gtk_locales = [
    "sk", "cs", "pl", "de", "fr", "vi", "ru", "zh_CN", "lt",
    "es", "hu", "nl", "it"
]

include_files = []

# Stuff required by GTK
gtk_dirs = ('etc', 'lib')
include_files += [(os.path.join(gnome_dll_path, x), x) for x in gtk_dirs]
include_files += [(os.path.join(gnome_dll_path, x), x) for x in missing_dll]

# GTK locales
include_files += [(os.path.join(gnome_dll_path, "share/locale", x, "LC_MESSAGES", "glib20.mo"),
                   "share/locale/" + x + "/LC_MESSAGES/glib20.mo") for x in enabled_gtk_locales]
include_files += [(os.path.join(gnome_dll_path, "share/locale", x, "LC_MESSAGES", "gtk30.mo"),
                   "share/locale/" + x + "/LC_MESSAGES/gtk30.mo") for x in enabled_gtk_locales]

# Data files
include_files += [x for x in os.listdir(".") if x.endswith(".ui")]
include_files += ["./icons"]
d = [(x, x) for x in find_mos("locale/")]
include_files += d
pprint.pprint(include_files)
# sys.exit(0)

executables = [
    Executable(
        "scripts/syncthing-gtk-exe.py",
        targetName="syncthing-gtk.exe",
        base="Win32GUI",
        icon="icons/st-logo-128.ico",
    ),
    Executable(
        "scripts/syncthing-gtk-exe.py",
        targetName="syncthing-gtk-console.exe",
        base="console",
        icon="icons/st-logo-128.ico",
    ),
]


def get_version():
    return "%s-win32" % (_get_version(),)


# Monkey-patch _AddVersionResource in cx_Freeze so win32verstamp will
# not bitch about non-numeric version
RE_NUMBER = re.compile(r'v?([0-9]+).*')


def extract_number(x): return RE_NUMBER.match(x).group(1) if \
    RE_NUMBER.match(x) else "0"


def win32version(x): return ".".join(
    [extract_number(i) for i in x.split(".")[0:4]])


Freezer._AddVersionResource = lambda self, exe: \
    stamp(exe.targetName, VersionInfo(
        win32version(self.metadata.version),
        comments=self.metadata.long_description,
        description=self.metadata.description,
        company=self.metadata.author,
        product=self.metadata.name,
        copyright=exe.copyright,
        trademarks=exe.trademarks
    ))

setup(
    name="Syncthing GTK",
    author="Kozec",
    version=get_version(),
    description="Windows port of Syncthing GTK",
    options=dict(
        build_exe=dict(
            includes=["gi"],
            packages=["gi", "bcrypt", "cffi"],
            include_files=include_files
        ),
    ),
    executables=executables
)

if 'build' in sys.argv:
    for ll in wrong_sized_dll:
        print("replacing " + ll)
        shutil.copy(
            os.path.join(gnome_dll_path, ll),
            os.path.join(build_dir, ll)
        )
    # Copy some theme icons
    sizes = ["16x16", "24x24", "32x32", "scalable"]
    icons = {
        "status": [
            "image-missing",
            "dialog-information",
            "dialog-warning",
            "dialog-error",
            "checkbox-symbolic",
            "checkbox-mixed-symbolic",
            "checkbox-checked-symbolic",
        ],
        "mimetypes":	["text-html"],
        "emblems":		["emblem-system-symbolic"],
        "apps":		["utilities-terminal"],
        "categories":	["preferences-system"],
        "places":		["user-home"],
        "actions": [
            "help-about",
            "edit-delete",
            "edit-undo",
            "application-exit",
            "system-shutdown",
            "document-open",
            "view-refresh",
            "open-menu-symbolic",
            "window-close-symbolic",
            "window-maximize-symbolic",
            "window-restore-symbolic",
            "window-minimize-symbolic",
            "list-add-symbolic",
            "list-remove-symbolic",
            "pan-up-symbolic",
            "pan-start-symbolic",
            "pan-end-symbolic",
            "pan-down-symbolic",
        ],
        "devices": [
            "drive-harddisk",
            "computer",
        ],
    }
    themes = ["Adwaita"]
    target_path = os.path.join(build_dir, "share/icons/")
    src_path = os.path.join(gnome_dll_path, "share/icons/")
    for theme in themes:
        for size in sizes:
            extension = "svg" if size == "scalable" else "png"
            for cat in icons:
                try:
                    os.makedirs(os.path.join(target_path, theme, size, cat))
                except Exception:
                    pass
                for icon in icons[cat]:
                    print("Copying icon %s/%s/%s/%s" % (theme, size, cat, icon))
                    icon = "%s.%s" % (icon, extension)
                    src = os.path.join(src_path, theme, size, cat, icon)
                    dst = os.path.join(target_path, theme, size, cat, icon)
                    if os.path.exists(src):
                        shutil.copy(src, dst)
        print("Copying theme index for" + theme)
        shutil.copy(
            os.path.join(src_path, theme, "index.theme"),
            os.path.join(target_path, theme, "index.theme")
        )

    print("Copying even more icons")
    shutil.copy(
        os.path.join(build_dir, "icons/128x128/apps/syncthing-gtk.png"),
        os.path.join(build_dir, "icons/syncthing-gtk.png")
    )

    print("Copying glib schemas")
    if not os.path.exists(os.path.join(build_dir, "/share/glib-2.0/schemas")):
        target_path = os.path.join(build_dir, "share/glib-2.0/schemas")
        src_path = os.path.join(gnome_dll_path, "share/glib-2.0/schemas")
        if not os.path.exists(target_path):
            os.makedirs(target_path)
        for filename in os.listdir(src_path):
            src = os.path.join(src_path, filename)
            target = os.path.join(target_path, filename)
            shutil.copy(src, target)

    print("Fixing https://github.com/syncthing/syncthing-gtk/issues/313")
    # Needs http://win-builds.org/1.5.0/packages/windows_32/FILENAME in in work directory
    FILENAME = "glib-networking-2.36.2-1-i686-w64-mingw32.txz"
    tmpdir = mkdtemp()
    cwd = os.getcwd()
    archive = open(FILENAME, "rb")
    os.chdir(os.path.join(build_dir))
    tarxz = Popen(['tar', 'Jxv', '--exclude', 'windows_32/share/*',
                   '--exclude', 'windows_32/doc/*', '--strip-components', "1"], stdin=PIPE)
    tarxz.communicate(archive.read())
    archive.close()
    os.chdir(cwd)
    if tarxz.returncode != 0:
        print("Failed to unpack " + FILENAME, file=sys.stderr)
        sys.exit(1)

    print("Storing version")
    with open(os.path.join(build_dir, "__version__"), "w") as f:
        f.write(get_version())
    with open(os.path.join(build_dir, "..", "version.nsh"), "w") as f:
        f.write('!define VERSION "{version}"'.format(version=get_version()))
