#!/usr/bin/env python
#

"""
gupload: graphterm-aware upload

To upload file:
   gupload directory/filename

To pipe uploaded data:
   gupload | cat > outfile

To switch stdout and stderr:
   gupload 3>&1 1>&2 2>&3-
"""

import base64
import json
import os
import sys
import tty
import termios

from optparse import OptionParser

import gterm

CHUNK_BYTES = 4096

Work_dir = os.getenv("PWD", "") or os.getcwd()

usage = "usage: %prog [-f] [<filepath/directory>]"
parser = OptionParser(usage=usage)
parser.add_option("-w", "--write",
                  action="store_true", dest="write", default=False,
                  help="Overwrite existing file")
parser.add_option("-o", "--stdout",
                  action="store_true", dest="stdout", default=False,
                  help="Use STDOUT for pagelet output")
parser.add_option("-q", "--quiet",
                  action="store_true", dest="quiet", default=False,
                  help="Quiet")
parser.add_option("", "--verbose",
                  action="store_true", dest="verbose", default=False,
                  help="Verbose")

(options, args) = parser.parse_args()

if len(args) > 1:
    print >> sys.stderr, "To many arguments"
    sys.exit(1)

assert sys.stdin.isatty()

to_dir = False
if args:
    expname = os.path.expanduser(args[0])
    filepath = os.path.normcase(os.path.normpath(os.path.join(Work_dir, expname)))
elif sys.stdout.isatty():
    filepath = "."
else:
    filepath = ""

if filepath:
    if os.path.exists(filepath):
        if os.path.isdir(filepath):
            to_dir = True
        elif not options.write:
            print >> sys.stderr, "Specify -w option to overwrite file %s" % filepath
            sys.exit(1)
    else:
        head, tail = os.path.split(filepath)
        if head:
            if os.path.exists(head):
                if not os.path.isdir(head):
                    print >> sys.stderr, "Cannot overwrite file %s" % head
                    sys.exit(1)
            else:
                print >> sys.stderr, "Please create directory %s" % head
                sys.exit(1)

params = {"display": "block", "current_directory": Work_dir}
html_headers = {"x_gterm_response": "upload_file",
                "x_gterm_parameters": params
                }
gterm.wrap_write("", headers=html_headers, stderr=not options.stdout)

Stdin_fd = sys.stdin.fileno()
Saved_settings = termios.tcgetattr(Stdin_fd)
Stdout_data = None

try:
    # Raw tty input without echo
    tty.setraw(Stdin_fd)
    line = ""
    header_line = ""
    while True:
        ch = sys.stdin.read(1)
        if ch == "\x03" or ch == "\x04": # ^C/^D
            gterm.write_blank(stderr=not options.stdout)
            sys.exit(1)
        if ch != "\n":
            line += ch
            continue
        if line:
            header_line = line
            line = ""
        else:
            # Terminal null line
            break

    if options.verbose:
        print >> sys.stderr, "header=%s\n" % (header_line,)

    # Process headers
    if not header_line:
        gterm.write_blank(stderr=not options.stdout)
        sys.exit(1)

    headers = json.loads(header_line)

    if "x_gterm_filepath" not in headers:
        gterm.write_blank(stderr=not options.stdout)
        sys.exit(1)

    content_type = headers["content_type"]
    if content_type.startswith("none/"):
        gterm.write_blank(stderr=not options.stdout)
        sys.exit(1)

    filename = headers["x_gterm_filepath"]
    expect_length = headers["x_gterm_length"]
    if options.verbose:
        print >> sys.stderr, "file=%s, type=%s, expect_len=%s\n" % (filename, content_type, expect_length)

    if expect_length:
        count = expect_length
        assert not (count % 4)
        prefix = ""
        content_list = []
        while count > 0:
            chunk = sys.stdin.read(min(count, CHUNK_BYTES))
            assert chunk
            count = count - len(chunk)
            line = prefix + chunk
            prefix = ""
            offset = len(line) % 4
            if offset:
                prefix = line[-offset:]
                line = line[:-offset]
            if options.verbose:
                print >> sys.stderr, "line(%d,%s)=%s" % (len(chunk), count, line,)
            content_list.append(base64.b64decode(line))
        assert not prefix
        content = "".join(content_list)
    else:
        b64_content = ""
        content = ""
except KeyboardInterrupt:
    sys.exit(1)
finally:
    termios.tcsetattr(Stdin_fd, termios.TCSADRAIN, Saved_settings)

gterm.write_blank(stderr=not options.stdout)

if filepath:
    if to_dir:
        filepath = os.path.join(filepath, filename)
    with open(filepath, "w") as f:
        f.write(content)
    if not options.quiet:
        print >> sys.stderr, "Uploaded file "+filepath
else:
    Stdout_data = content

if Stdout_data is not None:
    if options.stdout:
        sys.stderr.write(content)
    else:
        sys.stdout.write(content)
