#!/usr/bin/python2
###############################################################################
# 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.3"
upload_path = 'https://linx.li/upload/public/'


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

        yield data

        if not no_progress:
            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('-s', '--script', action="store_true", 
                    help="stdout will only print urls (no progress)")
parser.add_argument('files', nargs='*', metavar='file')
args = parser.parse_args()

try:

    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:
                if not os.path.exists(filename):
                    raise Exception("File {0} not found.".format(filename))

                basename = os.path.basename(filename)
                total = os.path.getsize(filename)

                if total == 0:
                    raise Exception("File {0} is empty".format(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, no_progress=args.script))
                    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:
                    data = sys.stdin.read().encode('utf-8')

                    if len(data) == 0:
                        raise Exception("stdin is empty.")

                    r = requests.put(
                        upload_path,
                        verify=True,
                        headers={
                            'Accept': "application/json",
                            'X-File-Expiry': args.expires,
                            'User-Agent': user_agent,
                        },
                        data=data)
                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__

except Exception as exc:
    print >> sys.stderr, str(exc)
    sys.exit(1)
