#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# xwot.py - Python tools for the extended Web of Things
# Copyright (C) 2015  Alexander Rüedlinger
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

__author__ = 'Alexander Rüedlinger'

from helper import OutputPrinter
from xwot.compiler.frontend import visitor


class ExpressBackendBuilder(visitor.BaseVisitor):

    def __init__(self):
        visitor.BaseVisitor.__init__(self)
        self._out = OutputPrinter()

    def before(self):
        self._out.code([
            '/*',
            ' * Generated by xwot compiler.',
            ' *',
            ' * Express.js xwot application.',
            ' */',
            '',
            'module.exports = function() {',
            self._out.indent([
                "var express = require('express');",
                'var app = express();',
            ])
        ], ["xwot", "app"])

    def after(self):
        self._out.code([
            self._out.indent(
                self._out.flatten([
                    [
                        "var %s = require('./%s.js');" % (node.name(), node.name()) for node in self._nodes
                    ],
                    [
                        "",
                        "//register resources"
                    ],
                    [
                        "%s(app);" % node.name() for node in self._nodes
                    ],
                    [
                        '',
                        'return app;'
                    ]
                ])
        ),
        "};"
        ], ["xwot", "app"])

        self._out.code([
            '/*',
            ' * Generated by xwot compiler.',
            ' *',
            ' * Express.js xwot application.',
            ' */',
            '',
            "var xwot_app = require('./xwot/app.js')();",
            '',
            "var server = xwot_app.listen(3000, function() {",
            self._out.indent([
                'var host = server.address().address;',
                'var port = server.address().port;',
                "console.log('Example app listening at http://%s:%s', host, port);"
            ]),
            '});'
        ], ["runserver"])

    def before_resource(self, node):
        self._out.code([
            '/*',
            ' * Generated by xwot compiler.',
            ' *',
            " * Type:       %s" % node.type(),
            " * Resource:   %s" % node.name(),
            " * Path:       %s" % node.fullpath(),
            '*/',
            '',
            'var setup = function(app) {',
        ], ["xwot", node.name()])

    def after_resource(self, node):
        self._out.code([
            '}',
            '',
            'module.exports = setup;'
        ], ["xwot", node.name()])

    def handle_entity(self, node):
        self.before_resource(node)
        self._out.code([
            self._out.indent([
                '/*',
                 " * GET '/'",
                 ' */',
                "app.get('/', function(req, res) { ",
                self._out.indent([
                    "res.send('Hello World at: %s');" % node.fullpath()
                ]),
                '});'
            ]),
        ], ["xwot", node.name()])
        self.after_resource(node)

    def handle_resource(self, node):
        for method in ['get', 'put']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_device_resource(self, node):
        for method in ['get', 'put']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_sensor_resource(self, node):
        for method in ['get']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_tag_resource(self, node):
        for method in ['get']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_context_resource(self, node):
        for method in ['get', 'put']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_service_resource(self, node):
        for method in ['get', 'post', 'put', 'delete']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_actuator_resource(self, node):
        for method in ['put']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def handle_publisher_resource(self, node):
        for method in ['get', 'post']:
            self._out.code([
                self._out.indent([
                    '/*',
                    " * %s '%s'" % (method.upper(), node.fullpath()),
                    ' */',
                    "app.%s('%s', function(req, res) { " % (method, node.fullpath()),
                    self._out.indent([
                            'res.end("Hello World at: %s");' % node.fullpath()
                        ]),
                    '});'
                ]),
            ], ["xwot", node.name()])

    def output(self):
        # get all created files
        files = self._out.flush()
        new_files_dic = {}

        for file_name, code in files.items():
            # append to each file its correct file extension
            new_files_dic[file_name + ".js"] = code

        return new_files_dic