#!python
"""LICENSE
Copyright 2017 Hermann Krumrey <hermann@krumreyh.com>

This file is part of ci-scripts.

ci-scripts 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.

ci-scripts 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 ci-scripts.  If not, see <http://www.gnu.org/licenses/>.
LICENSE"""

import os
import sys
import json
import requests
from typing import Dict, List
from ci_scripts.release_upload_common import parse_args


def upload_github_release(repository_owner: str,
                          repository_name: str,
                          version_number: str,
                          o_auth_token: str,
                          release_notes: str,
                          release_assets: List[Dict[str, str]],
                          branch: str):
    """
    Uploads a new release to github.com

    First, a new release is created. Afterwards, the script uploads all
    specified release assets to that Github release

    Does not work if the Release Tag already exists

    :param repository_owner: the destination repository owner
    :param repository_name:  the destination repository
    :param version_number:   the project's current version number
    :param o_auth_token:     the repository owner's oauth token
    :param release_notes:    release notes associated with this release
    :param release_assets:   the release assets, as a list of dictionaries
                             with the following keys:
                                path:         the file path to the asset
                                content_type: the asset's content type,
                                              for example
                                                  'application/java-archive'
                                              for .jar files
    :param branch:           the branch on which the release will be based on,
                             defaults to the master branch
    :return: None
    """

    # Format Strings for HTTP requests
    repository_identifier = repository_owner + "/" + repository_name
    repository_path = "repos/" + repository_identifier + "/releases"
    repository_api_url = "https://api.github.com/" + repository_path
    repository_upload_url = "https://uploads.github.com/" + repository_path
    o_auth_parameter = "access_token=" + o_auth_token

    post_url = repository_api_url + "?" + o_auth_parameter
    json_payload = {
        "tag_name": version_number,
        "target_commitish": branch,
        "name": "Release " + version_number,
        "body": release_notes,
        "draft": False,
        "prerelease": False
    }

    print(json_payload)

    # Create Tag and get Tag ID
    post_resp = requests.post(post_url, json=json_payload)
    if post_resp.status_code >= 300:
        print("Tag Creation Failed (" + str(post_resp.status_code) + ")")
        print(post_resp.reason)
        sys.exit(1)
    response = json.loads(post_resp.text)

    try:
        tag_id = response["id"]
    except KeyError:
        print(response)
        sys.exit(1)

    for asset in release_assets:

        file_path = asset["path"]
        file_name = os.path.basename(file_path)
        content_type = asset["content_type"]

        with open(file_path, "rb") as bytefile:
            data = bytefile.read()

        tag_api_url = repository_upload_url + "/" + str(tag_id)
        tag_api_url += "/assets?name=" + file_name + "&" + o_auth_parameter
        headers = {"Content-Type": content_type}

        # Upload Asset
        asset_resp = requests.post(url=tag_api_url, data=data, headers=headers)
        print("Asset Uploaded, Status: " + str(asset_resp.status_code))
        if asset_resp.status_code >= 300:
            print("Asset Upload Failed (" + str(asset_resp.status_code) + ")")
            print(asset_resp.reason)
            sys.exit(1)


def main():
    """
    Uploads a github release
    :return: None
    """

    args = parse_args()

    upload_github_release(
        repository_owner=os.environ["GITHUB_USERNAME"],
        repository_name=os.environ["CI_PROJECT_NAME"],
        version_number=args["tag_name"],
        o_auth_token=os.environ["GITHUB_TOKEN"],
        release_notes=args["notes"],
        release_assets=args["assets"],
        branch=args["branch"]
    )


if __name__ == "__main__":
    main()
