"""
novelWriter – AppImage Build
============================

This file is a part of novelWriter
Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors

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

This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations

import argparse
import datetime
import os
import shutil
import sys

from pathlib import Path

from utils.common import (
    ROOT_DIR, SETUP_DIR, appdataXml, copyPackageFiles, copySourceCode,
    extractVersion, freshFolder, makeCheckSum, removeRedundantQt, systemCall,
    toUpload, writeFile
)


def appImage(args: argparse.Namespace) -> None:
    """Build an AppImage."""
    try:
        import python_appimage  # noqa: F401 # type: ignore
    except ImportError:
        print(
            "ERROR: Package 'python-appimage' is missing on this system.\n"
            "       Please run 'pip install --user python-appimage' to install it.\n"
        )
        sys.exit(1)

    if sys.platform != "linux":
        print("ERROR: Command 'build-appimage' can only be used on Linux")
        sys.exit(1)

    print("")
    print("Build AppImage")
    print("="*120)

    mLinux = args.linux
    mArch = args.arch
    pyVer = args.python

    # Version Info
    pkgVers, _, relDate = extractVersion()
    relDate = datetime.datetime.strptime(relDate, "%Y-%m-%d")

    # Set Up Folder
    bldDir = ROOT_DIR / "dist_appimage"
    bldPkg = f"novelwriter-{pkgVers}-{mArch}"
    bldImg = f"{bldPkg}.AppImage"
    outDir = bldDir / bldPkg
    imgDir = bldDir / "appimage"
    appDir = bldDir / f"novelWriter-{mArch}"

    bldDir.mkdir(exist_ok=True)
    freshFolder(outDir)
    freshFolder(imgDir)
    freshFolder(appDir)

    # Remove old AppImages
    if images := bldDir.glob("*.AppImage"):
        print("Removing old AppImages")
        for image in images:
            image.unlink()

    # Copy novelWriter Source
    print("Copying novelWriter source ...")
    copySourceCode(outDir)

    print("Copying or generating additional files ...")
    copyPackageFiles(outDir)

    # Write Metadata
    writeFile(imgDir / "novelwriter.appdata.xml", appdataXml())
    writeFile(imgDir / "requirements.txt", str(outDir))
    writeFile(imgDir / "entrypoint.sh", (
        # f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{APPDIR}}/usr/lib/{mArch}-linux-gnu/\n"
        '{{ python-executable }} -sE ${APPDIR}/opt/python{{ python-version }}/bin/novelwriter "$@"'
    ))

    shutil.copyfile(SETUP_DIR / "data" / "novelwriter.desktop", imgDir / "novelwriter.desktop")
    print("Copied: novelwriter.desktop")

    shutil.copyfile(SETUP_DIR / "icons" / "novelwriter.png", imgDir / "novelwriter.png")
    print("Copied: novelwriter.png")

    # Build AppDir
    systemCall([
        sys.executable, "-m", "python_appimage", "build", "app", "--no-packaging",
        "-l", f"{mLinux}_{mArch}", "-p", pyVer, "appimage"
    ], cwd=bldDir)

    # Copy Libraries
    libPath = Path(f"/usr/lib/{mArch}-linux-gnu")
    siteDir = appDir / "opt" / f"python{pyVer}" / "lib" / f"python{pyVer}" / "site-packages"
    qt6Lib = siteDir / "PyQt6" / "Qt6" / "lib"
    shutil.copyfile(libPath / "libxcb-cursor.so.0", qt6Lib / "libxcb-cursor.so.0")

    # Remove Redundant
    removeRedundantQt(siteDir)

    # Build Image
    appToolExec = os.environ.get("APPIMAGE_TOOL_EXEC", "appimagetool")
    env = os.environ.copy()
    env["ARCH"] = mArch
    systemCall([
        appToolExec, "--no-appstream", "--updateinformation",
        f"gh-releases-zsync|vkbo|novelwriter|latest|novelwriter-*-{mArch}.AppImage.zsync",
        str(appDir), bldImg
    ], cwd=bldDir, env=env)

    updFile = bldDir / f"{bldImg}.zsync"
    bldFile = bldDir / bldImg
    shaFile = makeCheckSum(bldFile.name, cwd=bldDir)

    toUpload(bldFile)
    toUpload(updFile)
    toUpload(shaFile)

    return
