#! /usr/bin/python3
# -*- coding: utf-8 -*-

import os.path
import getopt
import sys
import base64
import requests
import json
from os.path import getsize, basename
from hashlib import md5

__author__ = "Alfonso Tierno, alfonso.tiernosepulveda@telefonica.com"
__date__ = "$2018-01-01$"
__version__ = "0.1"
version_date = "Jan 2018"


def usage():
    print("Usage: ", sys.argv[0], "[options]")
    print("      --version: prints current version")
    print("      -f|--file FILE: file to be sent")
    print("      -h|--help: shows this help")
    print("      -u|--url URL: complete server URL")
    print("      -s|--chunk-size SIZE: size of chunks, by default 1000")
    print("      -t|--token TOKEN: Authorizaton token, previously obtained from server")
    print("      -v|--verbose print debug information, can be used several times")
    return


if __name__=="__main__":

    try:
        # load parameters and configuration
        opts, args = getopt.getopt(sys.argv[1:], "hvu:s:f:t:",
                                   ["url=", "help", "version", "verbose", "file=", "chunk-size=", "token="])
        url = None
        chunk_size = 500
        pkg_file = None
        verbose = 0
        token = None

        for o, a in opts:
            if o == "--version":
                print ("upload version " + __version__ + ' ' + version_date)
                sys.exit()
            elif o in ("-v", "--verbose"):
                verbose += 1
            elif o in ("-h", "--help"):
                usage()
                sys.exit()
            elif o in ("-u", "--url"):
                url = a
            elif o in ("-s", "--chunk-size"):
                chunk_size = int(a)
            elif o in ("-f", "--file"):
                pkg_file = a
            elif o in ("-t", "--token"):
                token = a
            else:
                assert False, "Unhandled option"
        total_size = getsize(pkg_file)
        index = 0
        transaction_id = None
        file_md5 = md5()
        with open(pkg_file, 'rb') as f:
            headers = {
                "Content-type": "application/gzip",
                "Content-Filename": basename(pkg_file),
                "Accept": "application/json",
            }
            if token:
                headers["Authorization"] = token
            while index < total_size:
                chunk_data = f.read(chunk_size)
                file_md5.update(chunk_data)
                # payload = {"file_name": pkg_file, "chunk_data": base64.b64encode(chunk_data).decode("utf-8"),
                #            "chunk_size": chunk_size}
                if transaction_id:
                    headers["Transaction-Id"] = transaction_id
                if index+len(chunk_data) == total_size:
                    headers["Content-File-MD5"] = file_md5.hexdigest()
                #    payload["id"] = transaction_id
                headers["Content-range"] = "bytes {}-{}/{}".format(index, index+len(chunk_data)-1, total_size)
                # refers to rfc2616:  https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
                if verbose:
                    print("TX chunk Headers: {}".format(headers))
                r = requests.post(url, data=chunk_data, headers=headers, verify=False)
                if r.status_code not in (200, 201):
                    print("Got {}: {}".format(r.status_code, r.text))
                    exit(1)
                if verbose > 1:
                    print("RX {}: {}".format(r.status_code, r.text))
                response = r.json()
                if not transaction_id:
                    transaction_id = response["id"]
                index += len(chunk_data)
            if verbose <= 1:
                print("RX {}: {}".format(r.status_code, r.text))
            if "id" in response:
                print("---\nid: {}".format(response["id"]))
    except Exception as e:
        raise
