#!/usr/bin/env python
#

"""
gframe: Display file (or HTML from stdin) in inline iframe

For multiplexed display use:
   gframe -r 300 -l 50 -c 4 -b -t -p tty a b c d '[abcd]'

To recursively display terminal /local/tty1, use:
   gframe -r 300 -b --noheader -t /local/tty1/watch
"""

from __future__ import absolute_import, print_function

import math
import mimetypes
import os, os.path
import random
import sys
import termios
import time

from optparse import OptionParser

try:
    import gterm
except ImportError:
    import graphterm.bin.gterm as gterm

usage = "usage: %prog [file1|URL1] ..."

form_parser = gterm.FormParser(usage=usage, title="Display URL/file/stdin content within iframe", command="gframe")

form_parser.add_argument(label="URL/filename: ", help="URL/filename to display (optional)")
form_parser.add_option("prefix", "", short="p", help="URL/path prefix")
form_parser.add_option("suffix", "", short="s", help="URL/path suffix")
form_parser.add_option("opacity", 1.0, short="o", help="Frame opacity (default: 1.0)")
form_parser.add_option("columns", 0, short="c", help="Columns")
form_parser.add_option("width", "", short="w", help="Frame width (pixels/%)")
form_parser.add_option("rowheight", "", short="r", help="Frame row height")
form_parser.add_option("lastheight", "", short="l", help="Last row height")
form_parser.add_option("fullscreen", False, short="f", help="Fullscreen display")
form_parser.add_option("border", False, short="b", help="Include border")
form_parser.add_option("noheader", False, help="Suppress header")
form_parser.add_option("find_html", False, help="Skip input characters until '<DOCTYPE' or '<html'")
form_parser.add_option("echo", False, short="e", help="Do not suppress terminal echo")
form_parser.add_option("notebook", False, short="n", help="Interpret all arguments as IPython notebooks")
form_parser.add_option("terminal", False, short="t", help="Interpret all arguments as terminal URLs")
form_parser.add_option("trusted", False, help="Trust the frame content to execute commands")

(options, args) = form_parser.parse_args()

frame_content = None
trusted_content = options.trusted
if args:
    iframe_urls = []
    trust_list = []
    for arg in args:
        arg = options.prefix + arg + options.suffix
        if arg.startswith("http:") or arg.startswith("https:"):
            trust_list.append(False)
            iframe_urls.append(arg)
        elif options.terminal:
            trust_list.append(True)
            if "/" not in arg:
                arg = "/" + gterm.env("PATH").split("/")[1] + "/" + arg
            elif not arg.startswith("/"):
                sys.exit("Invalid terminal path %s; must begin with /" % arg)
            arg += "&" if "?" in arg else "/?"
            arg += "qauth=%[qauth]"
            iframe_urls.append(arg)
        elif options.notebook:
            trust_list.append(True)  # Notebook server will determine trust
            ipynb_parfile = gterm.get_param_filepath(gterm.APP_IPYNB_FILENAME)
            nb_dir, nb_url = "", ""
            try:
                with open(ipynb_parfile) as f:
                    nb_url, sep, nb_dir = f.read().strip().partition("#")
            except Exception as excp:
                sys.exit("Error in reading 'notebook-directory:port' info from %s: %s" % (ipynb_parfile, excp))

            relpath = os.path.relpath(os.path.abspath(arg), os.path.abspath(nb_dir))
            if relpath.startswith("/") or ".." in relpath:
                sys.exit("Notebook path %s not within server notebook directory %s" % (relpath, nb_dir))
            arg = "%s/notebooks/%s" % (nb_url, relpath)
            iframe_urls.append(arg)
        else:
            filepath = arg
            if not gterm.Cookie:
                # Display untrusted file in full window
                content_type, encoding = mimetypes.guess_type(filepath)
                try:
                    with open(filepath) as f:
                        frame_content = f.read()
                    if content_type.startswith("image/"):
                        gterm.display_data(content_type, frame_content, display="fullwindow" if options.fullscreen else "block")
                    else:
                        gterm.write_pagelet(frame_content, display="fullwindow")
                    sys.exit(0)
                except Exception as excp:
                    sys.exit("Error in reading file %s: %s" % (filepath, excp))
            # Display file
            trust_list.append(options.trusted)
            if not gterm.Export_host and options.trusted:
                iframe_urls.append(gterm.get_file_url(filepath, relative=True, exists=True, untrusted=not options.trusted))
            else:
                iframe_urls.append(gterm.create_blob(from_file=filepath, untrusted=not options.trusted))

            if not iframe_urls[-1]:
                print("File %s not found" % filepath, file=sys.stderr)
                sys.exit(1)

        if all(trust_list):
            # All terminals/notebooks
            trusted_content = True
else:
    try:
        frame_content = sys.stdin.read()
        if options.find_html:
            offset = frame_content.find("<!DOCTYPE")
            if offset < 0:
                offset = frame_content.find("<html")
            if offset >= 0:
                frame_content = frame_content[offset:]
                
    except (EOFError, KeyboardInterrupt):
        frame_content = None

    if not frame_content:
        print("Error in reading from stdin", file=sys.stderr)
        sys.exit(1)

    if not gterm.Cookie:
        # Display untrusted HTML content in full window
        gterm.write_pagelet(frame_content, display="fullwindow")
        sys.exit(0)

    iframe_urls = [gterm.create_blob(frame_content, content_type="text/html", untrusted=not trusted_content)]

if not trusted_content:             # Untrusted content must display full screen
    options.fullscreen = True

headers = {"opacity": options.opacity}
if not options.fullscreen and not options.rowheight:
    headers["autosize"] = True

if options.fullscreen or not trusted_content:
    headers["autoerase"] = True

if not trusted_content:
    headers["untrusted"] = True

add_class = "gterm-noheader" if options.noheader else ""
if options.border:
    add_class += " gterm-border"
IFRAMEFORMAT = '<iframe id="%s" class="gterm-iframe %s" src="%s" width="%s" %s></iframe>'

iframe_html = ""

nframes = len(iframe_urls)
ncols = int(options.columns) or nframes
nrows = ((nframes-1) // ncols) + 1

max_percent = 100.0 if options.noheader else 95.0
if options.rowheight:
    frameHeight = options.rowheight
elif options.columns:
    if options.lastheight and nrows > 1:
        if options.lastheight.endswith("%"):
            lh_precent = float(options.lastheight[:-1])
        else:
            termx, termy = gterm.env("DIMENSIONS").split(";")[1].split("x")
            lh_precent = 100.0*float(options.lastheight)/float(termy)
        height_percent = (max_percent - 5 - lh_precent) / (nrows - 1)
    else:
        height_percent = (max_percent - 5) / nrows
    frameHeight = str(height_percent)+"%"
else:
    frameHeight = str(max_percent)+"%" if options.fullscreen else ''

for j, url in enumerate(iframe_urls):
    irow = j//ncols
    if irow == nrows-1:
        # Last row
        n = ((nframes-1) % ncols)+1
        if options.lastheight:
            frameHeight = options.lastheight
    else:
        n = ncols
    if options.width:
        width = options.width
    else:
        width = str(100 if nframes == 1 else math.floor(96.0/n)) + "%"
    frameId = "gframe%09d" % random.randrange(0, 10**9)
    add_classes = add_class+("" if irow else " gterm-iframe-firstrow")
    iframe_html += gterm.iframe_html(url, add_classes=add_classes, width=width, height=frameHeight,
                                     header=not options.noheader, fullscreen=options.fullscreen)

if not options.noheader:
    iframe_html = gterm.iframe_header_html(iframe_html, fullscreen=options.fullscreen)

# TODO: Wrap iframe in div box with close X header for non fullscreen mode

if trusted_content:
    gterm.write_pagelet(iframe_html, display=("fullscreen" if options.fullscreen else "block"), add_headers=headers)
else:
    gterm.untrusted_wrap_write(iframe_html)

if options.fullscreen:
    if options.echo or not sys.stdout.isatty():
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            gterm.write_blank(exit_page=True)
    else:
        saved_settings = termios.tcgetattr(sys.stdout.fileno())
        new_settings = saved_settings[:]
        new_settings[3] = new_settings[3] & ~termios.ECHO   # Disable terminal echo
        try:
            termios.tcsetattr(sys.stdout.fileno(), termios.TCSADRAIN, new_settings)
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            gterm.write_blank(exit_page=True)
        finally:
            termios.tcsetattr(sys.stdout.fileno(), termios.TCSADRAIN, saved_settings)

