#!/usr/bin/python
###############################################################################
# linx - python uploader for linx.li
#
# author: mutantmonkey <mutantmonkey@mutantmonkey.in>
# author: andreimarcu <andrei@marcu.net>
###############################################################################
"""
Examples:

linx file.txt
    -> uploads file.txt with default options 

linx -e 60 file.txt
    -> uploads file.txt with an expiration time of 60 seconds

linx file1.txt file2.txt file3.txt
    -> uploads file{1,2,3}.txt 

echo "hello there" | linx
    -> uploads "hello there"

linx -d https://linx.li/3jah3.txt
    -> deletes 3jah3.txt from linx
"""

from urllib import quote
import argparse
import requests
import os.path
import json
import sys


logdir = os.path.join(os.path.expanduser("~"), ".local", "share")
if not os.path.exists(logdir):
    os.makedirs(logdir)

logpath = os.path.join(logdir, "linx.log")

user_agent = "linx-cli/0.1.1"
upload_path = 'https://linx.li/upload/public/'


def stream_upload(f, total, label="", chunk_size=64*1024):
    while True:
        data = f.read(chunk_size)
        if not data:
            sys.stdout.write("\r")
            sys.stdout.write(''.join([' ' for x in label]))
            sys.stdout.write("\r")
            sys.stdout.flush()
            break

        yield data
        sys.stdout.write("\r{label:40} {progress:7.2%}".format(
            label=label[-40:],
            progress=f.tell() / total))
        sys.stdout.flush()


parser = argparse.ArgumentParser(description="Upload files to linx.li.")
parser.add_argument('-e', '--expires', type=int, default=0,
                    help="The relative expiration time (in seconds) of the file.")
parser.add_argument('-d', '--delete', action="store_true", 
                    help="Deletes file from linx")
parser.add_argument('files', nargs='*', metavar='file')
args = parser.parse_args()


if args.delete:
    delete_keys = {}
    with open(logpath) as f:
        for line in f:
            line = line.split(':')
            delete_keys[line[0]] = line[1]

    for url in args.files:
        filename = os.path.basename(url)
        if not filename in delete_keys:
            raise Exception("File does not exist in log.")

        r = requests.delete(
            url,
            verify=True,
            headers={
                'X-Delete-Key': delete_keys[filename],
                'User-Agent': user_agent,
            })

        if r.status_code == 200:
            print("{filename}:{resp}".format(
                filename=filename,
                resp=r.text))
        else:
            print("{filename}:{errormsg}".format(
                filename=filename,
                errormsg=r.status_code))
else:
    logfile = open(logpath, 'a')

    if args.files:
        for filename in args.files:
            basename = os.path.basename(filename)
            total = os.path.getsize(filename)

            with open(filename, 'rb') as f:
                try:
                    r = requests.put(
                        upload_path + quote(basename),
                        verify=True,
                        headers={
                            'Accept': "application/json",
                            'X-File-Expiry': args.expires,
                            'X-Randomized-Barename': True,
                            'User-Agent': user_agent,
                        },
                        data=stream_upload(f, total, label=basename))
                except KeyboardInterrupt:
                    raise SystemExit

                data = json.loads(r.text)
                print(data['url'])
                logfile.write("{filename}:{delete_key}\n".format(**data))
    else:
        if not sys.stdin.isatty():
            try:
                r = requests.put(
                    upload_path,
                    verify=True,
                    headers={
                        'Accept': "application/json",
                        'X-File-Expiry': args.expires,
                        'User-Agent': user_agent,
                    },
                    data=sys.stdin.read().encode('utf-8'))
            except KeyboardInterrupt:
                raise SystemExit

            data = json.loads(r.text)
            print(data['url'])
            logfile.write("{filename}:{delete_key}\n".format(**data))
        
        else:
            parser.print_help()
            print __doc__
