#!/usr/bin/env python2.7

import sys
import os
import re
import subprocess
import time

PKGS_DIR    = "/var/efw/manager-addons-pkgs"
ADDONS_FILE = os.path.join(PKGS_DIR, "addons")
PKGS_FILE   = os.path.join(PKGS_DIR, "pkgs")

REMOTE_ADDONS_URL = "https://repo.openfw.com.br/manager-addons-pkgs/addons"
REMOTE_PKGS_URL   = "https://repo.openfw.com.br/manager-addons-pkgs/pkgs"

LINE_WIDTH = 60


def _rule(char="-"):
    print char * LINE_WIDTH


def _banner(title):
    _rule("=")
    print title.center(LINE_WIDTH)
    _rule("=")


def fetch_remote_list(url, dest_file, label):
    """Downloads dynamic lists (addons or pkgs) and writes to dest_file."""
    try:
        cmd = ["/usr/bin/curl", "-k", "-s", "-m", "15",
               "%s?t=%d" % (url, int(time.time()))]
        content = subprocess.check_output(cmd)
    except Exception as e:
        print "    [FAILED] %s list download error: %s" % (label, e)
        return False

    match = re.search(r'(\{.*\})', content, re.DOTALL)
    if not match:
        print "    [FAILED] %s invalid JSON response" % label
        return False

    try:
        with open(dest_file, 'w') as f:
            f.write(match.group(1))
        os.chmod(dest_file, 0o666)
    except IOError as e:
        print "    [FAILED] %s write error: %s" % (label, e)
        return False

    print "    [  OK  ] %s list updated" % label
    return True


def update_repo(list_type):
    """Updates dynamic lists and refreshes package repositories."""
    if not os.path.isdir(PKGS_DIR):
        try:
            os.makedirs(PKGS_DIR)
            os.chmod(PKGS_DIR, 0o777)
        except OSError as e:
            print "    [ERROR] Could not create %s: %s" % (PKGS_DIR, e)

    print "\n[*] Updating dynamic package lists..."
    if list_type == "addons":
        fetch_remote_list(REMOTE_ADDONS_URL, ADDONS_FILE, "Addons")
    elif list_type == "pkgs":
        fetch_remote_list(REMOTE_PKGS_URL, PKGS_FILE, "Packages")
    else:
        # If no specific list is defined, refresh both
        fetch_remote_list(REMOTE_ADDONS_URL, ADDONS_FILE, "Addons")
        fetch_remote_list(REMOTE_PKGS_URL, PKGS_FILE, "Packages")

    print "\n[*] Refreshing system repositories..."
    return ["/usr/local/bin/openfw-upgrade", "update"]


def _run(pid_file):
    if len(sys.argv) < 2:
        print "Usage: package-wrapper <action> [package]"
        return

    action = sys.argv[1]
    pkg = sys.argv[2] if len(sys.argv) > 2 else ""

    os.environ["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:" + os.environ.get("PATH", "")

    try:
        with open(pid_file, 'w') as f:
            f.write(str(os.getpid()))
    except IOError as e:
        print "Error writing PID file: %s" % e

    cmd = None

    ACTION_TITLES = {
        "install":     "INSTALL PACKAGE",
        "remove":      "REMOVE PACKAGE",
        "update":      "UPDATE PACKAGE",
        "update-repo": "UPDATE REPOSITORIES",
    }
    _banner(ACTION_TITLES.get(action, "PACKAGE MANAGER"))

    if action == "install":
        print "\n[*] Installing: %s" % pkg
        cmd = ["smart", "install", pkg, "-y"]
    elif action == "remove":
        print "\n[*] Removing: %s" % pkg
        cmd = ["smart", "remove", pkg, "-y"]
    elif action == "update":
        print "\n[*] Updating: %s" % pkg
        cmd = ["smart", "upgrade", pkg, "-y"]
    elif action == "update-repo":
        cmd = update_repo(pkg)
    else:
        print "Unknown action: %s" % action

    if cmd:
        try:
            subprocess.call(cmd, env=os.environ)
        except OSError as e:
            print "[ERROR] Execution failed: %s" % e


def main():
    pid_file = "/var/run/package-install.pid"
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

    try:
        _run(pid_file)
    except Exception as e:
        print "\n[ERROR] Unexpected failure: %s" % e
    finally:
        print ""
        _rule()
        print "Finished at %s" % time.ctime()
        _rule("=")

        if os.path.exists(pid_file):
            os.remove(pid_file)

if __name__ == "__main__":
    main()