#!/usr/bin/env python
from __future__ import print_function, division, unicode_literals
import json

from autobahn.twisted.websocket import WebSocketServerProtocol
from twisted.web.server import Site
from twisted.web.resource import Resource, NoResource
from twisted.python import log
from twisted.internet import reactor
from autobahn.twisted.websocket import WebSocketServerFactory
from autobahn.twisted.resource import WebSocketResource
from hcam_drivers.utils.web import FastFITSPipe


class MainHandler(Resource):
    def __init__(self, root):
        Resource.__init__(self)
        self.root = root

    def getChild(self, name, request):
        return DirHandler(self.root, name)


class DirHandler(Resource):
    isLeaf = True

    def __init__(self, root, path):
        Resource.__init__(self)
        self.root = root
        self.path = path

    def render_GET(self, request):
        return b'response'


class FileServerProtocol(WebSocketServerProtocol):

    def get_ffp(self, run_id):
        fname = '{}.fits'.format(run_id)
        path = os.path.join(self.db['dir'], fname)
        return FastFITSPipe(open(path, 'rb'))

    def onConnect(self, request):
        msg = 'Connection opened to access {}'
        print(msg.format('??'))
        run_id = 1
        try:
            self.ffp = self.get_ffp(run_id)
            self.sendMessage(self.encode({'status': 'OK'}))
        except IOError:
            print('No such run: ', run_id)
            self.sendMessage(self.encode({'status': 'no such run'}))
            self.sendClose(reason='no such run')

    def onClose(self, was_clean, code, reason):
        if was_clean:
            print('Socket closed cleanly')
        else:
            print('Socket closed (unclean)')

    def onMessage(self, payload, isBinary):
        if not isBinary:
            msg = json.loads(payload.decode('utf-8'))
        else:
            self.sendClose(1000, 'Cannot handle binary payloads')

        action = msg['action']
        if action == 'get_frame':
            self.get_frame(msg['frame_number'])
        elif action == 'get_hdr':
            self.get_main_header()
        elif action == 'get_next':
            self.get_next_frame()
        elif action == 'get_nframes':
            self.get_nframes()
        elif action == 'get_last':
            self.get_last_frame()


if __name__ == '__main__':

    import sys
    import os
    import argparse
    parser = argparse.ArgumentParser(description="HiPERCAM FileServer")
    parser.add_argument('--dir', action='store', default='.', help="directory to serve")
    parser.add_argument('--debug', action='store_true', help="debug fileserver")
    args = parser.parse_args()

    log.startLogging(sys.stdout)

    factory = WebSocketServerFactory("ws://127.0.0.1:8007")
    factory.protocol = FileServerProtocol
    resource = WebSocketResource(factory)

    # we serve static files under "/" ..
    # need to do something with /action=dir?
    root = MainHandler(os.path.abspath(args.dir))

    # and our WebSocket server under "/ws" (note that Twisted uses
    # bytes for URIs)
    root.putChild(b"ws", resource)

    # both under one Twisted Web Site
    site = Site(root)

    reactor.listenTCP(8007, factory)
    reactor.run()
