/****************************************************************************
**
** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the release tools of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

// constructor
function Component()
{
}

function originalHostOS()
{
    var targetOSName = "MacOS-MacOS_12-Clang-IOS-IOS_ANY-ARM64".toLowerCase();
    if (targetOSName.startsWith("macos")) {
        return "macOS";
    }
    else if (targetOSName.startsWith("windows")) {
        return "Windows";
    }
    else if (targetOSName.startsWith("linux")) {
        return "Linux";
    }
    else {
        console.log("MacOS-MacOS_12-Clang-IOS-IOS_ANY-ARM64 not defined!");
        return "";
    }
}

function originalQtHostPath()
{
    if (originalHostOS() == "Linux") {
        return "/home/qt/work/install";
    }
    else {
        return "/Users/qt/work/install";
    }
}

function newQtHostPath()
{
    if (installer.value("os") == "x11") {
        return installer.value("TargetDir") + "/6.6.0/gcc_64";
    }
    else if (installer.value("os") == "mac") {
        return installer.value("TargetDir") + "/6.6.0/macos";
    }
    else {
        return installer.value("TargetDir") + "/6.6.0/mingw_64";
    }
}

Component.prototype.createOperations = function()
{
    component.createOperations();

    var macHostSpec = "macx-clang";
    var linuxHostSpec = "linux-g++";
    var windowsHostSpec = "win32-g++";
    var targetDir = installer.toNativeSeparators(installer.value("TargetDir"));
    var qtPath = installer.toNativeSeparators(targetDir + "/6.6.0/ios");
    var cmakeBinary = "";
    var platform = "";
    var qmakeScript = "";
    var qmake6Script = "";
    var qtCMakeScript = "";
    var qtCMakePrivateScript = "";
    var qtCMakeStandaloneTestScript = "";
    var qtConfigureModuleScript = "";
    var targetQtConf = "";
    var qt6DependenciesCMakePath = "";
    var targetQtConf_documentation = "Documentation=../../Docs/Qt-6.6.0";
    var targetQtConf_examples = "Examples=../../Examples/Qt-6.6.0";
    var qtToolchainCmake = "";
    var qtBuildInternalsExtraCmake = "";
    var qtPathsScript = "";
    var qtPaths6Script = "";
    var qconfigFile = qtPath + "/mkspecs/qconfig.pri";
    var qdeviceFile = qtPath + "/mkspecs/qdevice.pri";

    var originalHostBinPath = originalQtHostPath() + "/bin";
    var originalHostTargetPath = originalQtHostPath() + "/target";
    var originalHostPrefix = "HostPrefix=../../";
    var originalHostData = "HostData=target";
    var originalHostSpec = "";
    var originalQmakePath = "";
    var originalLicheck = "";
    var originalQtPathsPath = "";
    var originalSetCMakePath = "";
    var originalBIPrefix = "";

    var newHostBinPath = installer.toNativeSeparators(newQtHostPath() + "/bin");
    var newSetCMakePath = "";
    var newHostPrefix = "";
    var newHostData = "";
    var newQtHostPathCmakeDir = "";
    var newHostSpec = "";
    var newLicheck = "";
    var newQtPathsPath = "";
    var newNDKHost = "";
    var newHostLibExecutables = "";

    // We need to add execute rights for the script if the script is created in a
    // windows host and used in unix one.
    var fromWindowsToUnix = false;

    // Set original values
    // Packages are done in macOS
    if (originalHostOS() == "macOS") {
        console.log("Using Android packages built on macOS host");
        originalSetCMakePath = "/Applications/CMake.app/Contents/bin/cmake";
        originalHostSpec = macHostSpec;
        originalLicheck = "QT_LICHECK = licheck_mac";
        originalBIPrefix = "/usr/local/Qt-6.6.0";
    }
    // Packages are done in windows
    else if (originalHostOS() == "Windows") {
        console.log("Using Android packages built on Windows host");

        // Set a flag to indicate that host build is from a windows
        fromWindowsToUnix = true;

        originalSetCMakePath = "C:/CMake/bin/cmake.exe";
        originalHostSpec = windowsHostSpec;
        originalLicheck = "QT_LICHECK = licheck.exe";
        originalBIPrefix = "C:/Qt/Qt-6.6.0";

        // Packages from windows has unix path separator until Qt 6.5.0 release.
        // After that it will have windows style one
        if (!(typeof(66) == 'number' && 66 < 65)) {
            originalHostBinPath = "\\Users\\qt\\work\\install\\bin";
        }
    }
    // Packages are done in linux
    else{
        console.log("Using Android packages built on Linux host");
        originalSetCMakePath = "/opt/cmake-*.*.*/bin/cmake";
        originalHostSpec = linuxHostSpec;
        originalLicheck = "QT_LICHECK = licheck64";
        originalBIPrefix = "/usr/local/Qt-6.6.0";
    }
    // Initialize new values based on installation os
    if (installer.value("os") == "x11") {
        platform = "linux";

        qmakeScript = qtPath + "/bin/qmake";
        qmake6Script = qtPath + "/bin/qmake6";
        qtCMakeScript = qtPath + "/bin/qt-cmake";
        qtCMakePrivateScript = qtPath + "/libexec/qt-cmake-private";
        qtCMakeStandaloneTestScript = qtPath + "/libexec/qt-cmake-standalone-test";
        qtConfigureModuleScript = qtPath + "/bin/qt-configure-module";
        targetQtConf = qtPath + "/bin/target_qt.conf";
        qtToolchainCmake = qtPath + "/lib/cmake/Qt6/qt.toolchain.cmake";
        qtBuildInternalsExtraCmake = qtPath + "/lib/cmake/Qt6BuildInternals/QtBuildInternalsExtra.cmake";
        qtPathsScript = qtPath + "/bin/qtpaths";
        qtPaths6Script = qtPath + "/bin/qtpaths6";
        qt6DependenciesCMakePath = qtPath + "/lib/cmake/Qt6/Qt6Dependencies.cmake";

        // Initialize variables used for patching
        newSetCMakePath = targetDir + "/Tools/CMake/bin/cmake";
        newHostPrefix = "HostPrefix=../../gcc_64";
        newHostData = "HostData=../android_%QT_PKG_ANDROID_TARGET_ARCH%";
        newHostSpec = linuxHostSpec;
        newLicheck = "QT_LICHECK = licheck64";
        newQtPathsPath = newHostBinPath + "/qtpaths";
        newQmakePath = newHostBinPath + "/qmake";
        newNDKHost = "linux-x86_64";
        newHostLibExecutables = "./libexec";
        originalQtPathsPath = originalHostBinPath + "/qtpaths";
        originalQmakePath = originalHostBinPath + "/qmake";
    }
    else if (installer.value("os") == "mac") {
        platform = "mac";

        qmakeScript = qtPath + "/bin/qmake";
        qmake6Script = qtPath + "/bin/qmake6";
        qtCMakeScript = qtPath + "/bin/qt-cmake";
        qtCMakePrivateScript = qtPath + "/libexec/qt-cmake-private";
        qtCMakeStandaloneTestScript = qtPath + "/libexec/qt-cmake-standalone-test";
        qtConfigureModuleScript = qtPath + "/bin/qt-configure-module";
        targetQtConf = qtPath + "/bin/target_qt.conf";
        qtToolchainCmake = qtPath + "/lib/cmake/Qt6/qt.toolchain.cmake";
        qtBuildInternalsExtraCmake = qtPath + "/lib/cmake/Qt6BuildInternals/QtBuildInternalsExtra.cmake";
        qtPathsScript = qtPath + "/bin/qtpaths";
        qtPaths6Script = qtPath + "/bin/qtpaths6";
        qt6DependenciesCMakePath = qtPath + "/lib/cmake/Qt6/Qt6Dependencies.cmake";

        // Initialize variables used for patching
        newSetCMakePath = targetDir + "/Tools/CMake/bin/cmake";
        newHostPrefix = "HostPrefix=../../macos";
        newHostData = "HostData=../ios";
        newHostSpec = macHostSpec;
        newLicheck = "QT_LICHECK = licheck_mac";
        newQtPathsPath = newHostBinPath + "/qtpaths";
        newQmakePath = newHostBinPath + "/qmake";
        newNDKHost = "darwin-x86_64";
        newHostLibExecutables = "./libexec";
        originalQtPathsPath = originalHostBinPath + "/qtpaths";
        originalQmakePath = originalHostBinPath + "/qmake";
    }
    else if (installer.value("os") == "win") {
        platform = "windows";
        // we don't need to add additional execute rules in windows environment
        fromWindowsToUnix = false;

        // Initialize variables used for patching
        qmakeScript = qtPath + "\\bin\\qmake.bat";
        qmake6Script = qtPath + "\\bin\\qmake6.bat";
        qtCMakeScript = qtPath + "\\bin\\qt-cmake.bat";
        qtCMakePrivateScript = qtPath + "\\bin\\qt-cmake-private.bat";
        qtCMakeStandaloneTestScript = qtPath + "\\bin\\qt-cmake-standalone-test";
        qtConfigureModuleScript = qtPath + "\\bin\\qt-configure-module";
        targetQtConf = qtPath + "\\bin\\target_qt.conf";
        qtToolchainCmake = qtPath + "\\lib\\cmake\\Qt6\\qt.toolchain.cmake";
        qtBuildInternalsExtraCmake = qtPath + "\\lib\\cmake\\Qt6BuildInternals\\QtBuildInternalsExtra.cmake";
        qtPathsScript = qtPath + "\\bin\\qtpaths.bat";
        qtPaths6Script = qtPath + "\\bin\\qtpaths6.bat";
        qt6DependenciesCMakePath = qtPath + "\\lib\\cmake\\Qt6\\Qt6Dependencies.cmake";

        // Initialize variables used for patching
        newSetCMakePath = installer.toNativeSeparators(targetDir + "/Tools/CMake_64/bin/cmake.exe");
        newHostPrefix = "HostPrefix=../../mingw_64";
        newHostData = "HostData=../android_%QT_PKG_ANDROID_TARGET_ARCH%";
        newHostSpec = windowsHostSpec;
        newLicheck = "QT_LICHECK = licheck.exe";
        newQtPathsPath = newHostBinPath + "\\qtpaths";
        newQmakePath = newHostBinPath + "\\qmake";
        newNDKHost = "windows-x86_64";
        newHostLibExecutables = "./bin";
        originalQtPathsPath = originalHostBinPath + "\\qtpaths";
        originalQmakePath = originalHostBinPath + "\\qmake";
    }
    // patch qmake (.bat)
    component.addOperation("Replace", qmakeScript, originalQmakePath, newQmakePath);

    // patch qt-cmake(.bat)
    component.addOperation("Replace", qtCMakeScript, originalSetCMakePath, newSetCMakePath, "regex");

    // Patch build time CMAke paths from qt-cmake-private(.bat) script
    component.addOperation("Replace", qtCMakePrivateScript, originalSetCMakePath, newSetCMakePath, "regex");

    // If we are using executables from windows in unix environment we need to add
    // execute rights for those; windows doesn't set it automatically at creating phase.
    if (fromWindowsToUnix) {
        console.log("Setting execute rights for needed files.");
        component.addOperation("Execute", "{0}", "chmod", "+x", qmakeScript);
        component.addOperation("Execute", "{0}", "chmod", "+x", qtCMakeScript);
        component.addOperation("Execute", "{0}", "chmod", "+x", qtPathsScript);
        component.addOperation("Execute", "{0}", "chmod", "+x", qtCMakePrivateScript);
        component.addOperation("Execute", "{0}", "chmod", "+x", qtCMakeStandaloneTestScript);
        component.addOperation("Execute", "{0}", "chmod", "+x", qtConfigureModuleScript);

        // scripts with '6' are available only from Qt 6.4.0 ->
        if ("660" == "dev" || 66 >= 64) {
            component.addOperation("Execute", "{0}", "chmod", "+x", qmake6Script);
            component.addOperation("Execute", "{0}", "chmod", "+x", qtPaths6Script);
            }
        }

    // Patch Host Prefix, Host Data and Host Spec paths from target_qt.conf
    component.addOperation("Replace", targetQtConf, originalHostPrefix, newHostPrefix);
    component.addOperation("Replace", targetQtConf, originalHostData, newHostData);
    component.addOperation("Replace", targetQtConf, originalHostSpec, newHostSpec);

    // Patch HostLibraryExecutables from target_qt.conf
    component.addOperation("LineReplace", targetQtConf, "HostLibraryExecutables=", "HostLibraryExecutables=" + newHostLibExecutables);

    // Append target_qt.conf with relative paths to documentation and examples
    component.addOperation("AppendFile", targetQtConf, targetQtConf_documentation);

    // Add a new line to targetQtConf which AppendFile operation doesn't add automatically
    if (installer.value("os") == "win") {
        // \r\n = CR + LF used as a new line character in Windows
        component.addOperation("AppendFile", targetQtConf, "\r\n");
    }
    else {
        // \n = LF (Line Feed) used as a new line character in Unix/macOS
        component.addOperation("AppendFile", targetQtConf, "\n");
    }
    component.addOperation("AppendFile", targetQtConf, targetQtConf_examples);

    // Patch Qt install path from qt.toolchain.cmake
    component.addOperation("Replace", qtToolchainCmake, originalQtHostPath(), newQtHostPath());

    // Patch Qt install paths from QtBuildInternalsExtra.cmake
    component.addOperation("Replace", qtBuildInternalsExtraCmake, originalBIPrefix, installer.value("TargetDir"));
    component.addOperation("Replace", qtBuildInternalsExtraCmake, originalHostTargetPath, qtPath);

    // Patch Qt install path from qtpaths(.bat)
    component.addOperation("Replace", qtPathsScript, originalQtPathsPath, newQtPathsPath);

    if ("660" == "dev" || 66 >= 64) {
        // Patch Qt install path from Qt6Dependencies.cmake if file exist; it isn't available before Qt 6.4.0
        component.addOperation("Replace", qt6DependenciesCMakePath, originalQtHostPath(), newQtHostPath());
        // patch qmake6(.bat) if file exist; it isn't available before Qt 6.4.0
        component.addOperation("Replace", qmake6Script, originalQmakePath, newQmakePath);
        // Patch Qt install path from qtpaths6(.bat) if file exist; it isn't available before Qt 6.4.0
        component.addOperation("Replace", qtPaths6Script, originalQtPathsPath, newQtPathsPath);
    }

    // Patch default ndk host from qdevice.pri
    component.addOperation("LineReplace", qdeviceFile, "DEFAULT_ANDROID_NDK_HOST =", "DEFAULT_ANDROID_NDK_HOST = " + newNDKHost);
    addInitQtPatchOperation(component, platform, qtPath, qmakeScript, "qt5");

    if (installer.value("SDKToolBinary") == "")
        return;

    // add Qt into QtCreator
    component.addOperation("Execute",
                           ["@SDKToolBinary@", "addQt",
                            "--id", component.name,
                            "--name", "Qt %{Qt:Version} for iOS",
                            "--type", "Qt4ProjectManager.QtVersion.Ios",
                            "--qmake", qmakeScript,
                            "UNDOEXECUTE",
                            "@SDKToolBinary@", "rmQt", "--id", component.name]);

    // create qt.conf file
    createQtConfFiles(component, installer.value("TargetDir") + "/6.6.0/ios", "Qt-6.6.0");

    // patch qconfig.pri
    // is this OpenSource installation?
    var isOpenSource = "true";
    if (['true', 'yes', '1'].indexOf(isOpenSource) >= 0) {
        newLicheck = "QT_LICHECK =";
        component.addOperation("LineReplace", qconfigFile, "QT_EDITION =", "QT_EDITION = OpenSource");
    }
    component.addOperation("Replace", qconfigFile, originalLicheck, newLicheck);
}
