#!/usr/bin/env python
import json
import sys
import os
from subprocess import check_call, check_output

ENV = "dev"


def get_rest_api_info(application):
    return json.loads(check_output("aws apigateway get-rest-apis --profile {}".format(application),
                                   shell=True))


def get_resources(application, rest_api_id):
    return json.loads(
        check_output("aws apigateway get-resources --rest-api-id {} --profile {}".format(rest_api_id, application),
                     shell=True))


def get_rest_api_id(rest_api, application):
    for item in rest_api["items"]:
        if item["name"] == ENV + "_" + application:
            return item["id"]


class Nucleic:
    def __init__(self, rest_api_id, parent_id):
        with open('package.json') as config_file:
            config = json.load(config_file)
            self.config = config

            # if rest_api_id is None:
            #     rest_api = get_rest_api_info(config["application"])
            #     rest_api_id = get_rest_api_id(rest_api, config["application"])
            #
            # if parent_id is None:
            #     self.resources = get_resources(config["application"], rest_api_id)
            #     self.get_resource_id("/")

            self.rest_api_id = rest_api_id
            self.exclude = "'aws_lambda' 'aws_lambda/*' 'build' 'build/*' 'Makefile'"
            self.type = config["type"]

            if self.type == "lambda":
                self.l_config = config["lambda"]
                self.lambda_name = self.config["application"] + "-" + self.config["name"]

            if self.type == "resource":
                print("")

    def get_resource_id(self, name):
        for resource in self.resources["items"]:
            if resource["path"] == name:
                print(resource)
                return resource["id"]

    def info(self):
        if self.type == "lambda":
            print(self.config["name"], self.config["version"])
        elif self.type == "resource":
            print("")

    def run(self):
        if self.type == "lambda":
            check_call("node-lambda run -H {} -j {} -x {}".format(self.l_config["handler"], self.l_config["event"],
                                                                  self.l_config["context"]), shell=True)

    def clean(self):
        if self.type == "lambda":
            check_call("rm -rf .build", shell=True)

    def build(self):
        if self.type == "lambda":
            self.clean()
            check_call("npm install", shell=True)
            check_call("mkdir -p .build/files", shell=True)
            check_call("cp -r node_modules .build/files/node_modules", shell=True)
            check_call("tsc --outDir .build/files", shell=True)
            check_call("find .build/files -type f -name '*.ts' -delete", shell=True)

            if "private_dependencies" in self.config:
                for key in self.config["private_dependencies"]:
                    self.install_dependencies(key, self.config["private_dependencies"][key])

    def install_dependencies(self, dependency, version):
        if version == "live":
            cwd = working_dir = os.getcwd()

            while "lib" not in os.listdir(os.getcwd()):
                os.chdir("..")
                working_dir = os.getcwd()

            dependency_path = "{}/node_modules/{}".format(cwd, dependency)
            source_path = "{}/lib/{}".format(working_dir, dependency)
            install_path = "{}/node_modules".format(cwd)

            if os.path.isdir(dependency_path):
                check_call("rm -r {}".format(dependency_path), shell=True)

            check_call("ln -s {} {}".format(source_path, install_path), shell=True)

            os.chdir(cwd)

    def package(self):
        if self.type == "lambda":
           self.build() 
           check_call("cd .build/files && zip -r ../{}.zip . -x {}".format(self.lambda_name, self.exclude), shell=True)

    def create(self):
        if self.type == "lambda":
            self.package()
            check_call(
                "aws lambda create-function --function-name {} --runtime {} "
                "--role {} --handler {} --zip-file fileb://.build/{}.zip --profile {}".format(
                    self.lambda_name, self.l_config["runtime"], self.l_config["role"], self.l_config["handler"],
                    self.lambda_name, self.config["application"]),
                shell=True)
            if self.type == "resource":
                check_output(
                    "aws apigateway create-resource --parent-id {} --path-part {} --rest-api-id {} --profile ${}",
                    shell=True)

    def update(self):
        if self.type == "lambda":
            self.package()
            check_call(
                "aws lambda update-function-code --function-name {} --zip-file fileb://.build/{}.zip --profile {}".format(
                    self.lambda_name, self.lambda_name, self.config["application"]), shell=True)
            check_call("rm -rf .build", shell=True)

nucleic = Nucleic(None, None)

for arg in sys.argv[1:]:
    getattr(nucleic, arg)()
