import os
from functools import partial

import sys
from direct.gui.DirectButton import DirectButton
from direct.gui.OnscreenImage import OnscreenImage
from direct.gui.OnscreenText import OnscreenText
from panda3d.core import TransparencyAttrib, Vec4

import helper
import sound_manager
from helper import base, googily, EASY, NORMAL, HARD, comic_neue, PAUSED, nexus, GAME_OVER_LISTENERS
from people.player import instance as player

PAUSE_MENU = 0
DIFF_SELECT = 1
INSTRUCTIONS = 2
CREDITS = 3
GAME_OVER = 4
VICTORY = 5
CURRENT_STATE = -1

game_started = False

BUTTON_COLOR = Vec4(1, 1, 1, 1)
MUTED_COLOR = Vec4(0.5, 0.5, 0.5, 1)


def toggle_pause(state=None):
    if not player.alive:
        state = True
    if state is None:
        state = not PAUSED[0]
    PAUSED[0] = state
    if not sound_manager.MUSIC_MUTE:
        sound_manager.music.set_volume(0.25 if PAUSED[0] else 0.5)
    if PAUSED[0]:
        menu.show()
    else:
        set_menu(PAUSE_MENU)
        menu.hide()


def back_or_pause():
    if PAUSED[0]:
        back()
    else:
        toggle_pause()


base.accept('escape', back_or_pause)


def set_menu(state):
    assert state in (PAUSE_MENU, DIFF_SELECT, INSTRUCTIONS, CREDITS, GAME_OVER, VICTORY)
    global CURRENT_STATE
    diff_select_menu.hide()
    credits_menu.hide()
    instructions_menu.hide()
    pause_menu.hide()
    go_menu.hide()
    victory_menu.hide()
    back_button.show()

    CURRENT_STATE = state

    if CURRENT_STATE == DIFF_SELECT:
        diff_select_menu.show()
    elif CURRENT_STATE == CREDITS:
        credits_menu.show()
    elif CURRENT_STATE == INSTRUCTIONS:
        instructions_menu.show()
    elif CURRENT_STATE == PAUSE_MENU:
        pause_menu.show()
    if CURRENT_STATE == GAME_OVER:
        back_button.hide()
        go_menu.show()

    if game_started:
        back_button['text'] = 'Resume' if CURRENT_STATE == PAUSE_MENU else 'Back'
    else:
        back_button['text'] = 'Start' if CURRENT_STATE == PAUSE_MENU else 'Continue'

    if CURRENT_STATE == VICTORY:
        building_counter.hide()
        victory_menu.show()


def diff(value):
    assert value in (EASY, NORMAL, HARD)
    helper.DIFFICULTY = value
    for b in diff_options:
        b.set_scale(0.1)
    diff_options[value].set_scale(0.2)
    diff_description.text = diff_description_text[value]
    if value == EASY: s = 'E'
    if value == NORMAL: s = 'N'
    if value == HARD: s = 'H'
    menu_buttons[0]['text'] = 'Difficulty (%s)'%s


def back():
    global game_started
    if CURRENT_STATE == PAUSE_MENU:
        game_started = True
        toggle_pause(False)
    else:
        if player.alive:
            set_menu(PAUSE_MENU)
        else:
            set_menu(GAME_OVER)


def update_building_counter(task):
    if game_started:
        building_counter.text = '{} offices destroyed:\n{}/{}'.format(
            helper.COLOR_TO_WIN, helper.BUILDINGS_DESTROYED, helper.BUILDINGS_TO_DESTROY)
    else:
        building_counter.text = 'Destroy {} {} offices to win'.format(
            helper.BUILDINGS_TO_DESTROY, helper.COLOR_TO_WIN
        )
    if helper.BUILDINGS_TO_DESTROY == helper.BUILDINGS_DESTROYED:
        game_won = True
        set_menu(VICTORY)
    return task.cont
base.task_mgr.add(update_building_counter)


menu = OnscreenImage(image='img/menu_bg.png', parent=base.pixel2d, scale=(256, 1, 256))
menu.set_transparency(TransparencyAttrib.M_alpha)
back_button = DirectButton(text='Resume', pos=(0, 0, -0.9), command=back, parent=menu)
back_button['text_font'] = nexus
back_button['relief'] = None
back_button.set_scale(0.2)

building_counter = OnscreenText(text='', pos=(0, -1.14, 0), scale=0.07, font=nexus, parent=menu,
                                fg=helper.color_vectors['dark ' + helper.COLOR_TO_WIN],
                                bg=(1, 1, 1, 1))

# region pause menu
pause_menu = menu.attach_new_node('pause menu')
title = OnscreenImage('img/menu_title.png', parent=pause_menu)
menu_buttons = [
    DirectButton(text='Difficulty', command=partial(set_menu, DIFF_SELECT), parent=pause_menu),
    DirectButton(text='Instructions', command=partial(set_menu, INSTRUCTIONS), parent=pause_menu),
    DirectButton(text='Credits', command=partial(set_menu, CREDITS), parent=pause_menu),
    DirectButton(text='Restart', command=partial(os.execl, sys.executable, sys.executable, *sys.argv), parent=pause_menu),
    DirectButton(text='Exit', command=sys.exit, parent=pause_menu),
]


def mute(sfx:bool):
    button = sfx_button if sfx else music_button
    if sfx:
        sound_manager.sfx_mute()
        mute = sound_manager.SFX_MUTE
    else:
        sound_manager.music_mute()
        mute = sound_manager.MUSIC_MUTE
    color = MUTED_COLOR if mute else BUTTON_COLOR
    button.set_color(color)


for i, button in enumerate(menu_buttons):
    button.set_pos(0, 0, -0.05 - i * 0.16)
    button.set_scale(0.16)
    button['text_font'] = nexus
    button['relief'] = None
sfx_button = DirectButton(image='img/sfx.png', command=partial(mute, True), parent=pause_menu, pos=(-0.8, 0, 0.8))
music_button = DirectButton(image='img/music.png', command=partial(mute, False), parent=pause_menu, pos=(-0.6, 0, 0.8))
for button in (sfx_button, music_button):
    button.set_scale(0.1)
    button['relief'] = None
    button.set_color(BUTTON_COLOR)

# endregion

# region game over menu
go_menu = menu.attach_new_node('game over menu')
go_buttons = [
    DirectButton(text='Credits', command=partial(set_menu, CREDITS), parent=go_menu),
    DirectButton(text='Restart', command=partial(os.execl, sys.executable, sys.executable, *sys.argv), parent=go_menu),
    DirectButton(text='Exit', command=sys.exit, parent=go_menu),
]
for i, button in enumerate(go_buttons):
    button.set_pos(0, 0, -0.5 - i * 0.16)
    button.set_scale(0.16)
    button['text_font'] = nexus
    button['relief'] = None
go_text = OnscreenText(text="You have died.\nThank you for playing!", parent=go_menu, pos=(0, 0.5, 0.5), scale=0.2, font=googily)
# endregion

victory_menu = menu.attach_new_node('victory menu')
victory_buttons = [
    DirectButton(text='Credits', command=partial(set_menu, CREDITS), parent=victory_menu),
    DirectButton(text='Restart', command=partial(os.execl, sys.executable, sys.executable, *sys.argv), parent=victory_menu),
    DirectButton(text='Exit', command=sys.exit, parent=victory_menu),
]
for i, button in enumerate(victory_buttons):
    button.set_pos(0, 0, -0.2 - i * 0.16)
    button.set_scale(0.16)
    button['text_font'] = nexus
    button['relief'] = None
victory_text = OnscreenText(text="You won!\nThank you for playing!", parent=victory_menu, pos=(0, 0.5, 0.5), scale=0.2, font=googily)

diff_select_menu = menu.attach_new_node('difficulty select menu')

diff_text = OnscreenText(text='Mathematics Difficulty', parent=diff_select_menu, pos=(0, 0.8, 0),
                         scale=0.2, font=googily)
diff_options = [
    DirectButton(text='Easy', pos=(-0.5, 0, 0.6), command=partial(diff,EASY), parent=diff_select_menu),
    DirectButton(text='Normal', pos=(0, 0, 0.6), command=partial(diff,NORMAL), parent=diff_select_menu),
    DirectButton(text='Hard', pos=(0.5, 0, 0.6), command=partial(diff,HARD), parent=diff_select_menu),
]

diff_description = OnscreenText(text='', parent=diff_select_menu, pos=(0, 0.4, 0), font=comic_neue, scale=0.07)

credits_text = """Lovingly Made
in 48 hours
for Ludum Dare 41

by
Amras"""
credits_menu = OnscreenText(text=credits_text, parent=menu, pos=(0, 0.5, 0.5), scale=0.15)

instructions_menu = menu.attach_new_node('instructions menu')
instructions_title = OnscreenText(text='CONTROLS', parent=instructions_menu, pos=(0, 0.8, 0), scale=0.2, font=nexus)
instructions_text = """WASD to move around
Left Mouse Button to talk to people

Right Mouse Button to control your gang:
click on yourself to call allies back
click on anyone not in your gang to attack them
click on a building to destroy it

Middle Mouse Button to rotate the camera

Esc to access this menu
"""
instructions_detail = OnscreenText(text=instructions_text, parent=instructions_menu, pos=(0, 0.7, 0), scale=0.07,
                                   font=comic_neue)

diff_description_text = [
    """Hold the Left Mouse Button to talk to people.
    
BLACK JACKETS:
Numbers ending with '1', '2', or '3'
won't like you and will attack

RED JACKETS:
Numbers ending with '7', '8', or '9'
will help you and fight for you

NORMAL is recommended
    """,
    """Hold the Left Mouse Button to talk to people.

BLACK JACKETS:
Numbers divisible by 4
won't like you and will attack

RED JACKETS:
Numbers divisible by 3 (but not 4)
will help you and fight for you

NORMAL is recommended
    """,
    """Hold the Left Mouse Button to talk to people.

BLACK JACKETS:
Prime numbers
won't like you and will attack

RED JACKETS:
Natural squares and non-prime triangle numbers
will help you and fight for you

NORMAL is recommended
    """,
]

for b in diff_options:
    b['text_font'] = googily
    b['relief'] = None
    b.set_scale(0.1)


diff(NORMAL)
set_menu(DIFF_SELECT)
toggle_pause()
GAME_OVER_LISTENERS.append(toggle_pause)
GAME_OVER_LISTENERS.append(partial(set_menu, GAME_OVER))
