#!/usr/bin/env python3
"""
Tornado server for delivering a metallic-look frame at /start.
Requires the tornado package: pip install tornado
Serves static files (e.g. local jQuery) from /static/; put jquery-3.6.0.min.js in static/js/
"""

import random
import tornado.ioloop
import tornado.web
import json
from map import Map, Star

# pool of unique star system names (each used only once per map)
NAME_POOL = [
    "Sol", "Alpha Centauri", "Barnard's Star", "Sirius", "Proxima Centauri",
    "Epsilon Eridani", "Wolf 359", "Luyten 726-8", "Ross 154", "Ross 248",
    "Epsilon Indi", "Kapteyn's Star", "Groombridge 34", "Tau Ceti",
    "Lalande 21185", "Van Maanen's Star", "Struve 2398", "UV Ceti",
    "Vega", "Fomalhaut", "Deneb", "Altair", "Betelgeuse", "Rigel",
    "Polaris", "Capella", "Procyon", "Achernar", "Spica", "Antares",
    "Aldebaran", "Regulus", "Canopus", "Arcturus", "Pollux", "Castor",
    "Mizar", "Alcor"
]

maps = {}
next_map_id = 1

class StartHandler(tornado.web.RequestHandler):
    def get(self):
        self.set_header('Content-Type', 'text/html')
        html = """<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Metallic Frame with Menu</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background: #222;
        }
        #frame {
            position: relative;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border: 40px solid;
            border-image: linear-gradient(45deg, #bbb, #eee, #bbb) 1;
            box-shadow:
                inset 0 0 20px rgba(0,0,0,0.7),
                0 0 20px rgba(255,255,255,0.1);
            background: #444;
        }
        /* Menu styles */
        #menu {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            background: rgba(34,34,34,0.9);
            padding: 0;
            margin: 0;
        }
        #menu ul {
            list-style: none;
            margin: 0;
            padding: 0;
        }
        #menu > ul > li {
            position: relative;
            display: inline-block;
            padding: 10px 20px;
            color: #fff;
            cursor: pointer;
        }
        #menu .submenu {
            display: none;
            position: absolute;
            top: 100%;
            left: 0;
            background: #333;
            list-style: none;
            margin: 0;
            padding: 0;
            min-width: 120px;
            z-index: 1000;
        }
        #menu .submenu li {
            padding: 8px 12px;
            color: #fff;
            cursor: pointer;
        }
        #menu .submenu li:hover {
            background: #444;
        }
        /* menu & map container layout */
        #menu {
            height: 40px;
            line-height: 20px;
        }
        #map-container {
            position: absolute;
            top: 40px;
            left: 0;
            right: 0;
            bottom: 0;
            overflow: auto;
        }
    </style>
    <script src="/static/js/jquery-3.6.0.min.js"></script>
    <script>
        $(function(){
            $('#gameMenu').click(function(e){
                e.stopPropagation();
                $('.submenu').toggle();
            });
            $('.submenu li').click(function(e){
                e.stopPropagation();
                var action = $(this).text();
                $('.submenu').hide();
                if (action === 'New Map') {
                    var dims = prompt('Enter rows,cols (e.g. 5,6)');
                    if (!dims) return;
                    var parts = dims.split(',');
                    var rows = parseInt(parts[0], 10);
                    var cols = parseInt(parts[1], 10);
                    if (isNaN(rows) || isNaN(cols)) {
                        alert('Invalid dimensions');
                        return;
                    }
                    $.ajax({
                        type: 'POST',
                        url: '/new_map',
                        data: JSON.stringify({rows: rows, cols: cols}),
                        contentType: 'application/json'
                    }).done(function(resp){
                        $('#map-container').html(resp.html);
                    }).fail(function(){
                        alert('Error creating new map');
                    });
                }
            });
            $(document).click(function(){
                $('.submenu').hide();
            });
        });
    </script>
</head>
<body>
    <div id="frame">
        <div id="menu">
            <ul>
                <li id="gameMenu">Game
                    <ul class="submenu">
                        <li>New Map</li>
                        <li>Load</li>
                    </ul>
                </li>
            </ul>
        </div>
        <div id="map-container"></div>
    </div>
</body>
</html>"""
        self.write(html)


class NewMapHandler(tornado.web.RequestHandler):
    def post(self):
        data = json.loads(self.request.body)
        rows = int(data.get('rows', 0))
        cols = int(data.get('cols', 0))
        if rows <= 0 or cols <= 0:
            self.set_status(400)
            self.write({'error': 'invalid dimensions'})
            return
        global next_map_id
        map_id = next_map_id
        next_map_id += 1
        m = Map(rows, cols)
        # randomly assign stars to tiles (10% chance each)
        for tile in m.tiles.values():
            if random.random() < 0.10:
                stype = random.choice(Star.ALLOWED_TYPES)
                tile.star = Star(stype, tile)
        # assign unique names to each star from the pool
        stars = [t.star for t in m.tiles.values() if hasattr(t, 'star')]
        if len(stars) > len(NAME_POOL):
            raise tornado.web.HTTPError(500, 'Not enough unique star names available')
        names = random.sample(NAME_POOL, len(stars))
        for star, name in zip(stars, names):
            star.name = name
        maps[map_id] = m
        html = m.render()
        self.set_header('Content-Type', 'application/json')
        self.write({'map_id': map_id, 'html': html})

def make_app():
    return tornado.web.Application([
        (r"/start", StartHandler),
        (r"/new_map", NewMapHandler),
        (r"/static/(.*)", tornado.web.StaticFileHandler, {"path": "static"}),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888, address="164.92.255.211")
    print("Tornado server running at http://164.92.255.211:8888/start")
    tornado.ioloop.IOLoop.current().start()