# -*- coding: utf-8 -*-

#Copyright © 2005 Pol Danilov
###############################################################################
#    This file is part of "SIL".
#
#    A copy of the GNU General Public License should be included with any
#    redistribution of this program in a file named "COPYING".
#
#    "SIL" 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 2 of the License, or
#    (at your option) any later version.
#
#    "SIL" 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 "SIL"; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
###############################################################################

from __main__ import (
    pygame, SIL_Engine, SILScreen, Fade, exit, Controller_Buttons,
    CLOCK
    )
from config import config

def ShowScreen(DisplayScreen):
    if (DisplayScreen == 'MAIN'): DisplayScreen = mainScreen
    if (DisplayScreen != mainScreen): SIL_Engine.ScreenStack.append(SIL_Engine.DisplayScreen)

    SIL_Engine.DisplayScreen = DisplayScreen

    DisplayScreen.display()

    
    pygame.key.set_repeat(260,40) # Fast menu scrolling (up/down)

    while 'Infinite Loop':
        CLOCK.tick(120)
        SIL_Engine.DisplayScreen.Menu.DoEvents()
        SIL_Engine.DisplayScreen.Menu.update()
        if SIL_Engine.DisplayScreen.title.text == 'GRAPHICS': renderEffects()
        elif SIL_Engine.DisplayScreen.title.text == False: renderDescription()# TUTORIAL SCREEN

class SILMnu(pygame.sprite.AbstractGroup):# group of SILBtn sprite objects
    """
    `SIL Menu Screen !'
    
    """

    # Menu item select sound...
    global BIP
    BIP = pygame.mixer.Sound('sound/bip2.ogg')
    BIP.set_volume(0.1)
        
    def __init__(self, menuButtons, smallbtns=False, btnwidth=193):
        pygame.sprite.AbstractGroup.__init__(self)
        self.menuButtons = menuButtons
        self.Controller_select = 0
        self.In_Column = 0
        self.In____ = False
        self.keyButtons = dict()
        self.smallbtns = smallbtns
        self.btnwidth = btnwidth
        self.spritelist = list()

        # Create intial buttons, and add them to the sprite class group
        for buttonText, buttonPos, function in self.menuButtons:
            if (buttonText, buttonPos, function) == self.menuButtons[0]:
                highlight = True
            else:
                highlight = False
            button = SILBtn(buttonPos, self.btnwidth, highlight, buttonText,function, self.smallbtns)
            self.add(button)
            self.spritelist.append(button)
            
        self.maxIndex = len(self)-1

        
        self.CurrentButton = pygame.sprite.GroupSingle()
        self.CurrentButton.add(self.spritelist[0])

        self.Menu_select = lambda: self.spritelist.index(self.CurrentButton.sprite)

    def DoEvents(self):
        if pygame.event.get(pygame.QUIT): exit()

        for event in pygame.event.get():

            # If we are on the mainScreen check for mouse events
            if (self == mainScreen.Menu) and \
               event.type in (pygame.MOUSEMOTION, pygame.MOUSEBUTTONUP) and \
               pygame.Rect(event.pos, (1, 1)).collidelist(self.spritelist) != -1:

                oldSelection = self.CurrentButton.sprite
                newSelection = self.spritelist[pygame.Rect(event.pos, (1, 1)).collidelist(self.spritelist)]

                if (newSelection != oldSelection):
                    self.CurrentButton.add(newSelection)

                if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                    self.CurrentButton.sprite.selected()

            if event.type == pygame.KEYDOWN:

                print 'pressed:', event.key
                self.keyPress(event.key)
                    


    def keyPress(self, key):
        eventDone = False
        playBIP = False
        if self.In____ == True and config.KEY_LIST[key]:
            config.CONTROLLER_LIST[self.Menu_select()][self.In_Column+1] = key
            config.save()
            self.keyButtons[self.CurrentButton.sprite.text()][self.In_Column].text = config.KEY_LIST[key]
            self.keyButtons[self.CurrentButton.sprite.text()][self.In_Column].drawButton(True)
            self.In____ = False
        elif key in (pygame.K_RETURN, pygame.K_KP_ENTER):
            if SIL_Engine.DisplayScreen.title.text == 'CONTROLLERS':
                self.keyButtons[self.CurrentButton.sprite.text()][self.In_Column].text = '---'
                self.keyButtons[self.CurrentButton.sprite.text()][self.In_Column].drawButton(True)
                self.In____ = True
            self.CurrentButton.sprite.selected()
        elif key in (pygame.K_DOWN, pygame.K_KP2) and self.Menu_select() < self.maxIndex:
            self.CurrentButton.add(self.spritelist[self.Menu_select()+1])


            if self.Controller_select < 6: self.Controller_select += 1
            eventDone = True
            playBIP = True
        elif key in (pygame.K_UP, pygame.K_KP8) and self.Menu_select() > 0:
            self.CurrentButton.add(self.spritelist[self.Menu_select()-1])

            if self.Controller_select > 0: self.Controller_select -= 1
            eventDone = True
            playBIP = True
        elif key == pygame.K_PAGEDOWN and self.Menu_select() < self.maxIndex:
            if self.Menu_select() < self.maxIndex-6: playBIP = True
            if self.Menu_select()+7 > self.maxIndex:
                self.CurrentButton.add(self.spritelist[-1])
            else:
                self.CurrentButton.add(self.spritelist[self.Menu_select()+7])

            self.Controller_select = 6

            eventDone = True
        elif key == pygame.K_PAGEUP and self.Menu_select() > 0:
            if self.Menu_select() > 6: playBIP = True
            if self.Menu_select()-7 < 0:
                self.CurrentButton.add(self.spritelist[0])
            else:
                self.CurrentButton.add(self.spritelist[self.Menu_select()-7])

            self.Controller_select = 0

            eventDone = True
        elif key in (pygame.K_LEFT, pygame.K_KP4):
            if self.CurrentButton.sprite.text() == 'WEATHER EFFECTS' and config.WEATHER_FX:
                config.WEATHER_FX = False
                eventDone = True
                playBIP = True
            elif self.CurrentButton.sprite.text() == 'PALETTE EFFECTS' and config.PALETTE_FX:

                config.PALETTE_FX = False
                eventDone = True
                playBIP = True
            elif SIL_Engine.DisplayScreen.title.text == 'CONTROLLERS' and self.In_Column == 1: 
                self.In_Column = 0
                eventDone = True
                playBIP = True
        elif key in (pygame.K_RIGHT, pygame.K_KP6):
            if self.CurrentButton.sprite.text() == 'WEATHER EFFECTS' and not config.WEATHER_FX:   
                
                config.WEATHER_FX = True
                eventDone = True
                playBIP = True
            elif self.CurrentButton.sprite.text() == 'PALETTE EFFECTS' and not config.PALETTE_FX:

                config.PALETTE_FX = True
                eventDone = True
                playBIP = True
            elif SIL_Engine.DisplayScreen.title.text == 'CONTROLLERS' and self.In_Column == 0:
                self.In_Column = 1
                eventDone = True
                playBIP = True
        elif key == pygame.K_ESCAPE:
            if SIL_Engine.DisplayScreen.title.text == 'CREDITS':#ResetCredits()
                list(credScreen.Menu.spritedict)[0].CreditsCount = 480
            if self.In____ == True:
                action = self.CurrentButton.sprite.text()
                savedKey = config.CONTROLLER_LIST[self.Menu_select()][self.In_Column+1]
                self.keyButtons[action][self.In_Column].text = config.KEY_LIST[savedKey]
                self.keyButtons[action][self.In_Column].drawButton(True)
                self.In____ = False
            elif (SIL_Engine.ScreenStack):
                SIL_Engine.DisplayScreen = SIL_Engine.ScreenStack.pop()
                SIL_Engine.DisplayScreen.display()
        if (playBIP): BIP.play()
        return eventDone

class SILCrd(pygame.sprite.Sprite):
    """
    Credits object
    """
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        
        in_file = open('data/KR3D17Z', 'r')
        Buffer = in_file.read().split('\n')
        Bufferlen = (len(Buffer)+1) *18
        in_file.close()

        self.image = pygame.Surface((439,Bufferlen)).convert()
        self.rect = self.image.get_rect()
        # 439 is the biggest x value of a rendered line (sloppy)

        y = 0
        for line in Buffer:
            if line in ('SIL', 'ORIGINAL SILENCER CREDITS'): textcolor = (255,0,0)
            elif line.isupper(): textcolor = (24,124,20)
            else: textcolor = (164,164,164)

            img = SILTxt(line, (0,0), 18, textcolor).Surface
            self.image.blit(img, (self.image.get_size()[0]/2-img.get_size()[0]/2, y))
            y += 18
        self.Len = Bufferlen
        self.CreditsCount = 480

    def update(self):
        self.CreditsCount -= 1
        if -self.CreditsCount > self.Len-33:
            self.CreditsCount = 480
            postEscape()
        self.rect.top = self.CreditsCount
        self.rect.left = 320-self.image.get_width()/2
        SIL_Engine.SIL_Surface.blit(self.image, self.rect.topleft)#, (0,0,439,self.Len))
        pygame.display.update(self.rect)
        CLOCK.tick(30)

class SILBtn(pygame.sprite.Sprite):
    """
    `Create a button with optional text'
        
    width         Width of the button
    height        Height of the button
    highlighted   Is it currently highlighted?
    text          Text to display on the button (SILTxt object)
    small         Small or large button?
    textsize      Size of font
    textcolor     RGB color of font
    halfsize      Width of the end of the buttons
    img           btn or btn2 (see above)
    Surface          Whole button surface
    widthlimit    Minimum width of button
    buttonPos     Position of the button (x,y)
    rectBox       A pygame.Rect object (used to detect mouse over
    """
    
    global btn, btn2, sbtn, sbtn2
  
    btn = pygame.image.load('data/btn.png').convert_alpha()     # large button unhighlighted
    btn2 = pygame.image.load('data/btn2.png').convert_alpha()   # large button highlighted
    sbtn = pygame.image.load('data/sbtn.png').convert_alpha()   # small button unhighlighted
    sbtn2 = pygame.image.load('data/sbtn2.png').convert_alpha() # small button highlighted

    global scroll_up2, scroll_down2
    scroll_up2 = pygame.image.load('data/scroll_up2.png').convert_alpha()
    scroll_down2 = pygame.image.load('data/scroll_down2.png').convert_alpha()


    # Constructor 
    def __init__(
        self, buttonPos, width=29, highlighted=False, text=None, function=None, small=False,
        textsize=18, textcolor=(4,76,0)
        ):

        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
         
        # Set the instance variables so we can reference them later
        self.highlighted = highlighted
        self.text = text
        self.function = function
        self.small = small
        self.textsize = textsize
        self.textcolor = textcolor
        self.rect = pygame.Rect(buttonPos[0],buttonPos[1],width,0)
        self.image = None
        self.addColor = (1,1,1)
        
        # Smallbutton
        if (self.small):
            self.rect.height = 27
            self.textsize = 13
            self.widthlimit = 24
            self.halfsize = 12

        # Largebutton
        else:
            self.rect.height = 33
            self.widthlimit = 29
            self.halfsize = 15

        self.drawButton(self.highlighted)

    def update(self):
        if self == SIL_Engine.DisplayScreen.Menu.CurrentButton.sprite:
            if self.highlighted: self.pulser()
            else: self.drawButton(True)
            
        elif self.highlighted: self.drawButton(False)
        self.blit()
        pygame.display.update(self.rect)
        
        if SIL_Engine.DisplayScreen == contrScreen:
            
            self.rect.topleft = (76,480)
            cs = contrScreen.Menu.Controller_select
            ms = contrScreen.Menu.Menu_select()
            ic = contrScreen.Menu.In_Column
            Action = self.text()
            top = ms - cs
            if self in contrScreen.Menu.spritelist[top:top+7]:

                y = contrScreen.Menu.spritelist.index(self)+cs-ms
                self.rect.topleft = (76,45*(y+2)-4)
                contrScreen.Menu.keyButtons[Action][0].rect.topleft = (302,45*(y+2)-4)
                contrScreen.Menu.keyButtons[Action][1].rect.topleft = (423,45*(y+2)-4)

                self.blit()
                if contrScreen.Menu.Controller_select == y:
                    if contrScreen.Menu.keyButtons[Action][ic].highlighted == False:
                        contrScreen.Menu.keyButtons[Action][ic].drawButton(True)
                    if contrScreen.Menu.keyButtons[Action][int(not ic)].highlighted == True:
                        contrScreen.Menu.keyButtons[Action][int(not ic)].drawButton(False)
                    contrScreen.Menu.keyButtons[Action][ic].pulser()
                else:            
                    if contrScreen.Menu.keyButtons[Action][0].highlighted == True:
                        contrScreen.Menu.keyButtons[Action][0].drawButton(False)
                    if contrScreen.Menu.keyButtons[Action][1].highlighted == True:
                        contrScreen.Menu.keyButtons[Action][1].drawButton(False)

                contrScreen.Menu.keyButtons[Action][0].blit()
                contrScreen.Menu.keyButtons[Action][1].blit()
                pygame.display.update(contrScreen.Menu.keyButtons[Action][0].rect)
                pygame.display.update(contrScreen.Menu.keyButtons[Action][1].rect)
        
            if ms == cs:
                SIL_Engine.SIL_Surface.blit(contrScreen.background, (547,89), (547,89,15,12) )
                pygame.display.update(pygame.Rect(547,89,15,12))
            else:
                SIL_Engine.SIL_Surface.blit(scroll_up2, (547,89) )
                pygame.display.update(pygame.Rect(547,89,15,12))
    
            if ms+6-cs == contrScreen.Menu.maxIndex:
                SIL_Engine.SIL_Surface.blit(contrScreen.background, (547,378), (547,378,15,12) )
                pygame.display.update(pygame.Rect(547,378,15,12))
            else:
                SIL_Engine.SIL_Surface.blit(scroll_down2, (547,378) )
                pygame.display.update(pygame.Rect(547,378,15,12))


    # Will draw a new button, or an already existing button
    # highlighted or not
    def drawButton(self, highlight=False, changeText=True):
        self.highlighted = highlight

        if (self.small): images = (sbtn, sbtn2, (4,76,0), (104, 164, 128) )
        else: images = ( btn,  btn2, (4,76,0), (104, 164, 128) )

        self.img = images[highlight]
        if changeText: self.textcolor = images[highlight+2]
        

        # Make sure width is at least widthlimit
        if self.rect.width < self.widthlimit: self.rect.width = self.widthlimit
            
        # Create the button surface, the first 2
        # only need to be done once
        self.image = pygame.Surface((self.rect.width,self.rect.height)).convert_alpha()
        self.image.fill((255,255,255,0))
        self.image.blit(self.img, (0,0), pygame.Rect(0,0,self.halfsize,self.rect.height) )

        # Construct button to the width
        for x in range(self.rect.width-self.widthlimit+1):
            self.image.blit(self.img, (self.halfsize+x,0), (self.halfsize+1,0,1,self.rect.height))
        self.image.blit(self.img,(self.halfsize+x,0), (self.halfsize+3,0,self.halfsize,self.rect.height))

        # Create text surface if necessary, change text color, set position, and blit it on
        if (self.text):
            if isinstance(self.text,SILTxt): self.text = self.text()
            self.text = SILTxt(self.text, (0,0), self.textsize, self.textcolor, bold=False)
            if self.rect.width < self.text.Surface.get_width():
                self.rect.width = self.text.Surface.get_width()+10
                    
            self.text.setTextPos((self.image.get_width()/2-self.text.Surface.get_width()/2,5))
            self.image.blit(self.text.Surface, self.text.textPos)

    # Handles the event where the button is selected
    def selected(self):
        if self.function != None: # check if button does anything
            if isinstance(self.function, SILScreen): ShowScreen(self.function)
            else: self.function()

    # Handles animation (mainly pulsing text) one frame at a time
    def pulser(self):
            
        self.textcolor = pygame.color.add(self.textcolor,self.addColor)
        
        if (self.textcolor[0] >= 140): self.addColor = (-1,-1,-1)
        elif (self.textcolor[0] <= 100): self.addColor = (1,1,1)

        self.drawButton(self.highlighted, False)

    # Draw the button onto the main surface
    def blit(self): SIL_Engine.SIL_Surface.blit(self.image, self.rect.topleft)

class SILTxt(object):
    """
    `Render True-Silencer-style text'

    text        The text to render
    textPos     The position to render it at
    textsize    The size of the font
    textcolor   Color of the font
    bold        Boolean, bold or not
    
    """
    
    global OCR_A
    OCR_A = {}
    
    def __init__(self, text, textPos=(0,0), textsize=18, textcolor=(4,76,0), bold=False):

        # Instance variables
        self.text = text
        self.textPos = textPos # (x,y)
        self.textsize = textsize
        self.textcolor = textcolor
        self.bold = bold

        if OCR_A.has_key(self.textsize) == False:
            OCR_A[self.textsize] = pygame.font.Font('data/ocr-a.ttf', self.textsize)

        self.Surface = OCR_A[self.textsize]
        if (self.bold): self.Surface.set_bold(True)
        self.Surface = self.Surface.render(self.text, True, self.textcolor).convert_alpha()
        if (self.bold): OCR_A[self.textsize].set_bold(False)

    def __call__(self): return self.text

    # Change the position of the text
    def setTextPos(self, textPos): self.textPos = textPos
    
    # Will render the font onto the surface with the new text color
    def setTextColor(self, txtcolor):
        self.Surface = OCR_A[self.textsize]
        self.textcolor = txtcolor
        self.Surface = self.Surface.render(self.text, True, self.textcolor).convert_alpha()
        return self

    # Draw the surface onto the main surface
    def blit(self): SIL_Engine.SIL_Surface.blit(self.Surface, self.textPos)

def makeKeyButtons():
    contrScreen.Menu.keyButtons = dict()
    
    for buttonText,key1,key2 in config.CONTROLLER_LIST:
        contrScreen.Menu.keyButtons[buttonText] = (
            SILBtn((302,480),111, False, config.KEY_LIST[key1],None, False, 13),
            SILBtn((423,480),111, False, config.KEY_LIST[key2],None, False, 13)
            )
    return contrScreen.Menu.keyButtons


def renderEffects():
#    from config import config

    L_ON = pygame.image.load('data/L_ON.png').convert_alpha()
    L_OFF = pygame.image.load('data/L_OFF.png').convert_alpha()
    R_ON = pygame.image.load('data/R_ON.png').convert_alpha()
    R_OFF = pygame.image.load('data/R_OFF.png').convert_alpha()

    from menu import graphScreen
    SIL_Engine.SIL_Surface.blit(graphScreen.background,(400,133),pygame.Rect(400,133,57,83))
    
    if config.WEATHER_FX == True:
        SIL_Engine.SIL_Surface.blit(L_OFF, (400,133))
        SIL_Engine.SIL_Surface.blit(R_ON, (440,133))
    else:
        SIL_Engine.SIL_Surface.blit(L_ON, (400,133))
        SIL_Engine.SIL_Surface.blit(R_OFF, (440,133))
        
    if config.PALETTE_FX == True:
        SIL_Engine.SIL_Surface.blit(L_OFF, (400,183))
        SIL_Engine.SIL_Surface.blit(R_ON, (440,183))
    else:
        SIL_Engine.SIL_Surface.blit(L_ON, (400,183))
        SIL_Engine.SIL_Surface.blit(R_OFF, (440,183))
    pygame.display.flip()
    
    
def renderDescription():
    SIL_Engine.SIL_Surface.blit(tut,(375,75),(375,75,300,300))
    one[SIL_Engine.DisplayScreen.Menu.Menu_select()].blit()
    pygame.display.flip()

def InitializeDescriptions():
    global one, tut
    one = (
        SILTxt('Jabber-based chat',(375,75),15,(255,255,255)),
        SILTxt('will be developed',(375,75),15,(255,255,255)),
        SILTxt('before tutorial mode.',(375,75),15,(255,255,255))
        )
    tut = pygame.image.load('data/tutorial.png').convert()


def postEscape(): pygame.event.post(pygame.event.Event(pygame.KEYDOWN,{'key':pygame.K_ESCAPE}))
    
### SILScreen Initializations
######################################################################################################
######################################################################################################
######################################################################################################


from chat.Chat import CHAT_screen
contrScreen = SILScreen('CONTROLLERS', 'data/options.png',
              SILMnu(
                    Controller_Buttons,
                     False,217
                   ),
                    False,
                    False,
                    False
                        )


graphScreen = SILScreen('GRAPHICS', 'data/tutorial.png',
              SILMnu((
                     ( 'WEATHER EFFECTS',(162,132), None ),
                     ( 'PALETTE EFFECTS',(162,182), None ),
                     ( 'EXIT',           (162,232), lambda: (config.save(),postEscape()) ))
                    ),
                      False,
                      False,
                      False
                       )

optScreen = SILScreen('OPTIONS', 'data/options.png',
            SILMnu((
                   ( 'CONTROLLERS',   (223,132), contrScreen),
                   ( 'GRAPHICS',      (223,182), graphScreen ),
                   ( 'RESET DEFAULTS',(223,232),
                     lambda: (config.reset(),makeKeyButtons(),postEscape()) ),
                   ( 'EXIT',          (223,282), postEscape ))
                  ),
                    False,
                    False,
                    False
                     )

tutScreen = SILScreen(False, 'data/tutorial.png',
            SILMnu((
                   ( 'SOON',                 (61,94),  None ),
                   ( 'COMING SOONISH',       (61,124), None ),
                   ( 'IN A SOON WHILE',      (61,154), None )),
#                  ( 'I - Player Movement',  (61,94)  ),
#                  ( 'II - Agent Base',      (61,124) ),
#                  ( 'III - Secret Recovery',(61,154) ))
                   True,
                    236 ),
                    False,
                    False,
                    False,
                    (( SILTxt('SELECT TUTORIAL', (75,34), 26,(64,148,84)), False),)
                       )

credScreen = SILScreen('CREDITS', 'data/tutorial.png',
            SILMnu((
                   ( 'EXIT CREDITS',    (640,480), postEscape ),),),
                    True,
                    False,
                    False,
                       ((pygame.Surface((640,480)),(0,0)),)
                    )

mainScreen = SILScreen('', 'data/MARSm.png',
             SILMnu((
                    ( 'TUTORIALS',  (292, 34 ), tutScreen ),
                    ( '<BETA> CHAT',(380, 127), CHAT_screen ),
                    ( 'OPTIONS',    (409, 221), optScreen ),
                    ( 'CREDITS',    (380, 315), credScreen ),
                    ( 'EXIT GAME',  (291, 409), exit ))
                   ),
                    True,
                    True,
                    True,
                    (( pygame.image.load('1n7r0/SIL28.png').convert_alpha(),                (83,217)),
                    ( SILTxt('Copyright 2005, 2006 [C], Pol Danilov', (10,463),10,(64,148,84),True), False),
                    ( SILTxt(SIL_Engine.ver, (490,463), 10, (64, 148, 84), True),           False),
                    ( SILTxt('www.nongnu.org/sil', (30,370), 13, (64, 148, 84), True),  False))
                      )
