"""
Copyright (C) 2008  Matthew and Joey Marshall <joey@arcticpaint.com>

See main.py for full notice.
"""
from __future__ import division
import sys, os
import rabbyt, math
from pyglet.text import HTMLLabel
import snowui
from pyglet.window import mouse, key

from gamelib import __version__

import urllib2
from distutils.version import StrictVersion
import webbrowser

import simplejson
import threading

menu_button = snowui.widget_setting(snowui.Button, bounds="rect",
        default_color=(1,1,1,1), hover_color=(1,1,1,.5))


class Menu(snowui.GUI):

    news = ""
    news_download_started = False
    mute = False

    def __init__(self, window):
        snowui.GUI.__init__(self, bounds="always")

        self.window = window

        self.gui_view = snowui.View(window)
        self.gui_view.x = self.gui_view.width/2
        self.gui_view.y = self.gui_view.height/2

        self.x = self.gui_view.width/2 - 1024/2
        self.y = self.gui_view.height/2 - 768/2

        try:
            fp = open("settings.json")
            self.settings = simplejson.load(fp)
            fp.close()
        except IOError:
            self.settings = {"mute":False}
        Menu.mute = bool(self.settings["mute"])

        self.main_plane = snowui.Widget(texture="menu_bg.png", bounds="always", rx=0, ry=0)
        self.map_plane = snowui.Widget(texture="map_bg.png", bounds="always", rx=0, ry=0)
        self._selected_plane = None

        self.do_play = False
        if self.settings.has_key("selected_map"):
            self.selected_map = self.settings["selected_map"]
        else:
            self.selected_map = "Tutorial"

        if self.settings.has_key("fullscreen"):
            if self.settings["fullscreen"]:
                self.window.set_fullscreen(True)
        else:
            self.window.set_fullscreen(True)


        self.setup_maps_plane()
        self.setup_main_plane()

        window.event(self.on_resize)
        self.news_displayed = False


    def on_resize(self, width, height):
        self.gui_view.width = width
        self.gui_view.height = height
        self.gui_view.x = self.gui_view.width/2
        self.gui_view.y = self.gui_view.height/2
        self.window.set_mouse_cursor(self.cursors["default"])
        self.x = self.gui_view.width/2 - 1024/2
        self.y = self.gui_view.height/2 - 768/2

    def _set_selected_plane(self, p):
        #for c in p.children:
            #c.y = rabbyt.ease_out(start=-50, end=c.y, dt=1)

        if self._selected_plane:
            self.remove(self._selected_plane)
        self._selected_plane = p
        self.add(self._selected_plane)


    selected_plane = property(lambda self:self._selected_plane,
            _set_selected_plane)


    def setup_maps_plane(self):

        self.maps = []
        for d in os.listdir("data/maps/"):
            if d[0] != "_" and d:
                d = d[:-5]
                self.maps.append(d)
        self.maps.sort()
        if self.selected_map not in self.maps:
            self.selected_map = "Tutorial"

        # When stuff like this is done it's to ensure that missing settings
        # don't cause a problem (for instance when running a new version).
        if not self.settings.has_key("awards"):
            self.settings["awards"] = {}
            self.save_settings()



        mb = snowui.Widget(shape=(0,230,1024,0), alpha=0, rxy=(0,0),
                bounds="rect")
        self.map_plane.add(mb)
        self.setup_mapdetail(self.selected_map, first=True)

        self._selcted_menu_map = snowui.Widget(texture="menu/selection.png")
        self._selcted_menu_map.is_active = False
        mb.add(self._selcted_menu_map)

        self._maps_list = []
        for i,m in enumerate(self.maps):
            num_per_row = 4
            row = i//num_per_row
            n = Text(m, font_size=14, color=(0,0,0,255), rx=20, ry=20)
            o = snowui.Button(texture="menu/selection.png", icon=n,
                bounds="rect", rx=30+240*i-(row*240*num_per_row), ry=160-row*52,
                callback=self.setup_mapdetail, cb_data=m)
            o.default_color = o.rgba = (1,1,1,1)
            mb.add(o)
            self._maps_list.append(o)
            #if m in self.settings["awards"]:
                #a = snowui.Widget(texture=self.settings["awards"][m]+".png",
                        #rx=170, ry=40)
                #o.add(a)

        self.select_map(self.selected_map)

    def setup_mapdetail(self, mapname, first=False):
        if not first:
            self.map_plane.remove(self.md)
        self.select_map(mapname)
        self.md = md = snowui.Widget(texture="menu/map_detail.png", rx=540,
                ry=245, bounds="rect")
        self.map_plane.add(md)

        #mmap = snowui.Widget(texture="menu/moc_map.png", rx=260, ry=0,
                #bounds="rect")
        #md.add(mmap)

        #m = snowui.Widget(texture="menu/man1.png", rx=15, ry=2)
        #m.is_active = False
        #md.add(m)


        fp = open("data/maps/%s.json"%mapname)
        data = simplejson.load(fp)

        n = Text(mapname, rx=20, ry=270, font_size=22,
                color=(0,0,0,255))
        md.add(n)

        t = data["settings"]["description"]
        n = Text(t, rx=20, ry=240, font_size=13, color=(0,0,0,255),
                multiline=True, width=450)
        md.add(n)

        p = snowui.Button(texture="menu/play.png", rx=330, ry=2,
                callback=self.play, bounds="rect")
        md.add(p)


    def setup_main_plane(self):
        #self.selected_map_label = Text(self.selected_map, rx=780, ry=170, font_size=17)
        #self.main_plane.add(self.selected_map_label)

        #l = Text("Press F to toggle fullscreen mode.", rx=1024/2, ry=20,
                #font_size=14, anchor_x="center")
        #self.main_plane.add(l)

        l = Text("Version: "+str(__version__), rx=10, ry=748,
                font_size=12,)
        self.main_plane.add(l)

        self.main_plane.add(snowui.Widget(texture="menu_buttons_bg.png", rx=764, ry=24))

        #self.main_plane.add(menu_button(texture="map_select.png", rx=737, ry=158,
            #callback=self._set_selected_plane, cb_data=self.map_plane))
        #self.main_plane.add(menu_button(texture="menu_button.png", rx=743, ry=150,
            #callback=self._set_selected_plane, cb_data=self.map_plane))

        #self.main_plane.add(menu_button(texture="l_arrow.png", rx=730, ry=160,
            #callback=self.select_map, cb_data=-1))
        #self.main_plane.add(menu_button(texture="r_arrow.png", rx=950, ry=160,
            #callback=self.select_map, cb_data=1))

        self.mute_button = menu_button(texture="mute.png", rx=20, ry=20,
                callback=self.do_mute)
        self.main_plane.add(self.mute_button)
        self.check_mute()

        self.fullscreen_button = menu_button(texture="fs_up.png", rx=90, ry=20,
                callback=self.do_fullscreen)
        self.main_plane.add(self.fullscreen_button)
        self.check_fullscreen()

        self.main_plane.add(menu_button(texture="play.png", rx=783, ry=250,
                callback=self._set_selected_plane, cb_data=self.map_plane))
        self.main_plane.add(menu_button(texture="quit.png", rx=780, ry=37,
                callback=sys.exit, cb_data=0))

        self.new_version = None

        self.main_plane.add(snowui.Button(texture="arcticpaint_logo.png",
                rx=1024-80, ry=768-80, default_color=(1,1,1,1),
                hover_color=(1,1,1,.5),
                callback=webbrowser.open,
                cb_data="http://arcticpaint.com/"))

        #if self.settings.has_key("highscore"):
            #scores = self.settings["highscore"]
            #scores.sort(key=lambda t:t[1])
            #scores.reverse()
            #if len(scores) > 10:
                #scores = scores[:10]
            #tx = "Top Ten Scores:<br>"
            #for name,score in scores:
                #tx += name+": "+str(score)+"<br>"
            #self.highscore = Text(tx, rx=20, ry=330, multiline=True, width=190,
                #color=(255,255,255,140), font_size=10)
            #self.main_plane.add(self.highscore)

        if not Menu.news and not Menu.news_download_started:
            if "-dev" not in sys.argv:
                self.start_news_download()
            else:
                print "(dev) skipping updates download"
                Menu.news = "dev mode"

    def do_mute(self):
        Menu.mute = not Menu.mute
        self.check_mute()
        self.save_settings()

    def check_mute(self):
        if Menu.mute:
            self.mute_button.texture = "mute_onn.png"
        else:
            self.mute_button.texture = "mute.png"
        self.mute_button.shape.left = 0
        self.mute_button.shape.bottom = 0

    def do_fullscreen(self):
        self.window.set_fullscreen(not self.window.fullscreen)
        self.check_fullscreen()
        self.save_settings()

    def check_fullscreen(self):
        if self.window.fullscreen:
            self.fullscreen_button.texture = "fs_down.png"
        else:
            self.fullscreen_button.texture = "fs_up.png"
        self.fullscreen_button.shape.left = 0
        self.fullscreen_button.shape.bottom = 0

    def save_settings(self):
        self.settings["mute"] = Menu.mute
        self.settings["selected_map"] = self.selected_map
        self.settings["fullscreen"] = self.window.fullscreen
        out = simplejson.dumps(self.settings, sort_keys=False, indent=4)
        fp = open("settings.json", "w")
        fp.write(out)
        fp.close()

    def start_news_download(self):
        self._download_thread = threading.Thread(target=self._load_news_thread)
        self._download_thread.setDaemon(True)
        self._download_thread.start()
    
    def _load_news_thread(self):
        try:
            fp = urllib2.urlopen("http://arcticpaint.com/games/gondola/news.txt")
            Menu.news = fp.read()
            fp.close()
        except:
            pass

    def display_news(self):
        news = Menu.news
        try:
            latest_version, news = news.split("\n", 1)
            latest_version = latest_version.split(":")[1]
        except:
            return

        #news = "<br>".join(news.split("\n")[:3])

        #self.news_text.text = news
        #self.news_text.color = (255,255,255,140)

        try:
            if StrictVersion(latest_version) > StrictVersion(__version__):
                self.new_version = Text("A new version is availible!<br>\
                        Download it at <i>ArcticPaint.com</i>", rx=252/2, ry=25,
                        anchor_x="center", font_size=12, color=(0,0,0,255),
                        multiline=True, width=240)
                self.hud = snowui.Button(texture="hud.png", bounds="rect",
                    rx=1024/2-126, ry=0, hover_color=(1,1,1,0.7),
                    callback=webbrowser.open,
                    cb_data="http://arcticpaint.com/games/gondola/")
                self.hud.add(self.new_version)
                self.main_plane.add(self.hud)
                self.hud.alpha = rabbyt.lerp(start=0, end=1, dt=.2)
            self.news_displayed = True
        except ValueError:
            return

    def select_map(self, map):
        self.selected_map = map
        #self.selected_plane = self.main_plane
        #self.selected_map_label.text = map
        self.save_settings()

        if hasattr(self, "_selcted_menu_map"):
            m = self._maps_list[self.maps.index(map)]
            self._selcted_menu_map.rxy = m.rxy

    def render(self):
        snowui.GUI.render(self)
        #self.news_text.draw()
        if self.news and not self.news_displayed:
            self.display_news()

    def setup(self):
        """
        A hack. We can't push any more handlers until after the UI is pushed.
        """
        self.mouse_xy = (110,110)
        self.keyboard = key.KeyStateHandler()
        self.window.push_handlers(self.keyboard)

    def handle_mouse_motion(self, x, y, dx, dy):
        self.mouse_xy = (x,y)

    def play(self):
        self.do_play = True

    def handle_key_press(self, symbol, *args):
        if symbol == key.ESCAPE:
            if self.selected_plane == self.main_plane:
                sys.exit(0)
            else:
                self.selected_plane = self.main_plane
        elif symbol == key.F:
            self.do_fullscreen()


class Text(snowui.Widget):
    def __init__(self, text, anchor_x="left", color=(255,255,255,200),
            font_size=20, multiline=False, width=None, **kwargs):
        snowui.Widget.__init__(self, **kwargs)

        self.font_size = font_size
        self.color = color
        self.multiline = multiline
        self.width = width

        self.label = HTMLLabel(text, x=self.x, y=self.y,
                anchor_x=anchor_x, multiline=multiline, width=width)
        self._format()


    def _format(self):
        self.label.color = self.color
        self.label.font_size = self.font_size


    def render(self):
        self.label.x = self.x
        self.label.y = self.y
        self.label.draw()


    def set_text(self, t):
        self.label.text = t
        self._format()
    text = property(lambda self:self.label.text, set_text)



class MapOption(snowui.Button):
    def __init__(self, map, **kwargs):
        snowui.Button.__init__(self, texture="ingame_menu.png", bounds="rect", **kwargs)
        self.rgba = self.default_color = (.8,.8,.8,1)
        self.hover_color = (1,1,1,1)

        fp = open("data/maps/%s.json"%map)
        data = simplejson.load(fp)



        self.add(snowui.Widget(texture="dificulty.png", rx=25, ry=20))
        d = data["settings"]["dificulty"]
        l = 198*d
        r = (l-50)/200
        g = 1-((l+50)/200)
        w = snowui.Widget(shape=(0,0,l, 9), rx=26, ry=21, rgba=(r,g,0,.5))
        self.add(w)

