#-------------------------------------------------------------------------------
# Name:        CvDotMapOverlayScreen.py
# Purpose:     Custom Screen for the dot map of the Strategy Overlay
#
# Author:      Del69, EmperorFool
#
# Created:     09/01/2009
#-------------------------------------------------------------------------------

from CvPythonExtensions import *
import BugUtil
import CvStrategyOverlay
import CvUtil
import PlayerUtil
import sys

X, Y = 0, 1    # used in point tuples instead of creating a new class

gc = CyGlobalContext()
g_DotMap = None

class CvDotMapOverlayScreen:
    """
    Screen for the dot map of the strategy overlay.
    """
    def __init__(self, screenID):
        self.screenID = screenID
        self.SCREEN_NAME = "DotMapOverlayScreen"
        #---------------------------------------------------------------------------
        # Panel IDS
        #---------------------------------------------------------------------------
        self.PANEL_ID = "DotMapColorPanel"
        #---------------------------------------------------------------------------
        # Color Panel Coordinates
        #---------------------------------------------------------------------------
        self.PANEL_X = 10
        self.PANEL_Y = 110
        self.PANEL_MARGIN = 12
        self.PANEL_EXTRA_W = 1
        self.PANEL_EXTRA_H = 5
        #---------------------------------------------------------------------------
        # Color Panel Widgets
        #---------------------------------------------------------------------------
        self.COLOR_WIDGET_W = 22
        self.COLOR_WIDGET_H = 25
        self.COLOR_WIDGET_ACTUAL_H = 20
        self.COLOR_WIDGET_PREFIX = "DotMapColorWidget"
        self.COLOR_WIDGET_IDS = []
        #-------------------------------------------------------------------------------
        # Constants
        #-------------------------------------------------------------------------------
        self.HIGHLIGHT_CROSS_LAYER = 8
        self.FIRST_CROSS_LAYER = 9
        self.PLOT_LAYER = PlotLandscapeLayers.PLOT_LANDSCAPE_LAYER_NUMPAD_HELP
        self.DOT_STYLE = PlotStyles.PLOT_STYLE_DOT_TARGET
        self.NO_DOT_STYLE = PlotStyles.PLOT_STYLE_NONE
        self.BFC_OFFSETS = []
        for x in range(-2, 3):
            for y in range(-2, 3):
                if abs(x) != 2 or abs(y) != 2:
                    self.BFC_OFFSETS.append((x, y))
        #---------------------------------------------------------------------------
        # State variables
        #---------------------------------------------------------------------------
        self.currentColor = 0
        self.bLeftMouseDown = False
        self.bRightMouseDown = False
        self.currentLayer = self.FIRST_CROSS_LAYER
        self.currentPoint = None
    #-------------------------------------------------------------------------------
    # Initialization Functions
    #-------------------------------------------------------------------------------
    def initVars(self):
        """
        Initializes the variables for the screen.
        """
        global g_DotMap
        g_DotMap = CvStrategyOverlay.getDotMap()
        for index in range(len(CvStrategyOverlay.COLOR_KEYS)):
            self.COLOR_WIDGET_IDS.append(self.COLOR_WIDGET_PREFIX + str(index))

    def isOpen(self):
        """
        Returns True if the screen is open.
        """
        return self.getScreen().isActive()
    #-------------------------------------------------------------------------------
    # Required civ4 functions
    #-------------------------------------------------------------------------------
    def getScreen(self):
        """
        Returns the CyGInterfaceScreen object for this screen.
        """
        return CyGInterfaceScreen(self.SCREEN_NAME, self.screenID)

    def hideScreen(self):
        """
        Hides the screen.
        """
        g_DotMap.unhighlightCity()
        CyInterface().setInterfaceMode(InterfaceModeTypes.INTERFACEMODE_SELECTION)
        screen = self.getScreen()
        screen.hideScreen()

    def update(self, fDelta):
        """
        Called each update cycle, checks for mouse button clicks when screen is up.
        """
        if CyInterface().isLeftMouseDown():
            if not self.bLeftMouseDown:
                self.onLeftMouseDown()
            self.bLeftMouseDown = True
        else:
            self.bLeftMouseDown = False
        if CyInterface().isRightMouseDown():
            if not self.bRightMouseDown:
                self.onRightMouseDown()
            self.bRightMouseDown = True
        else:
            self.bRightMouseDown = False

    def handleInput(self, inputClass):
        """
        Handles widget input.
        """
        BugUtil.debugInput(inputClass)
        if inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED and inputClass.getFunctionName() == self.COLOR_WIDGET_PREFIX:
            self.onColorButton(inputClass.getID())
            return 1
        return 0

    def interfaceScreen(self):
        """
        Initializes and shows the screen.
        """
        screen = self.getScreen()
        if screen.isActive():
            return
        screen.setCloseOnEscape(False)
        screen.setAlwaysShown(True)
        screen.setForcedRedraw(True)
        screen.setDimensions(0, 0, screen.getXResolution(), screen.getYResolution())
        screen.showScreen(PopupStates.POPUPSTATE_IMMEDIATE, True)
        self.initVars()
        self.createColorPanel()
        self.onMouseOverPlot()

    #-------------------------------------------------------------------------------
    #   Widget Adding/Updating Functions
    #-------------------------------------------------------------------------------
    def createColorPanel(self):
        """
        Creates the color selection panel.
        """
        screen = self.getScreen()
        count = len(CvStrategyOverlay.COLOR_KEYS)
        width = CvStrategyOverlay.PALETTE_WIDTH
        self.ROWS = (count - 1) / width + 1
        if self.ROWS == 1:
            self.COLUMNS = count
            self.PANEL_W = self.COLOR_WIDGET_W * self.COLUMNS
        else:
            self.COLUMNS = width
            self.PANEL_W = self.COLOR_WIDGET_W * width
        self.PANEL_W += 2 * self.PANEL_MARGIN + self.PANEL_EXTRA_W
        self.PANEL_H = self.ROWS * self.COLOR_WIDGET_ACTUAL_H + 2 * self.PANEL_MARGIN + self.PANEL_EXTRA_H
        #self.PANEL_Y = screen.getYResolution() - self.PANEL_H - 20
        #if CyInterface().getShowInterface() == InterfaceVisibility.INTERFACE_SHOW:
        #   self.PANEL_Y -= 164
        screen.addPanel(self.PANEL_ID, u"", u"", True, False, self.PANEL_X, self.PANEL_Y, self.PANEL_W, self.PANEL_H, PanelStyles.PANEL_STYLE_BLUELARGE)
        for index, color in enumerate(CvStrategyOverlay.COLOR_KEYS):
            row = index / width
            column = index % width
            x = self.PANEL_X + self.PANEL_MARGIN + column * self.COLOR_WIDGET_W
            y = self.PANEL_Y + self.PANEL_MARGIN + row * self.COLOR_WIDGET_ACTUAL_H
            szBar = self.COLOR_WIDGET_IDS[index]
            screen.addStackedBarGFC(szBar, x, y, self.COLOR_WIDGET_W, self.COLOR_WIDGET_H, 1, WidgetTypes.WIDGET_GENERAL, -1, -1)
            screen.setStackedBarColors(szBar, 0, gc.getInfoTypeForString(color))
            screen.setBarPercentage(szBar, 0, 100.0)

    def selectColor(self, index):
        """
        Updates the selected color and layer given the button index.
        """
        self.currentColor = gc.getInfoTypeForString(CvStrategyOverlay.COLOR_KEYS[index])  # index
        self.currentLayer = index + self.FIRST_CROSS_LAYER

    #-------------------------------------------------------------------------------
    #   Input handlers
    #-------------------------------------------------------------------------------
    def onColorButton(self, color):
        """
        Called on Color Button input.
        """
        g_DotMap.unhighlightCity()
        self.selectColor(color)
        g_DotMap.highlightCity(self.currentPoint, self.currentColor)
    
    def onLeftMouseDown(self):
        """
        Called on left mouse click on the main ui.
        """
        if self.currentPoint is not None:
            g_DotMap.unhighlightCity()
            grid = 6
            layer = self.FIRST_CROSS_LAYER + (self.currentPoint[X] % grid) * grid + (self.currentPoint[Y] % grid)
            g_DotMap.addCityAt(self.currentPoint, self.currentColor, layer)
            self.resetInterfaceMode()

    def onRightMouseDown(self):
        """
        Called on right mouse click on the main ui.
        """
        if self.currentPoint is not None:
            g_DotMap.unhighlightCity()
            g_DotMap.removeCityAt(self.currentPoint)
            self.resetInterfaceMode()

    def onMouseOverPlot(self, argsList=None):
        """
        Called from CvOverlayScreenUtils when mousing over a plot when the screen is active.
        Updates the current plot and its x/y location.
        """

        # remove the current city
        g_DotMap.unhighlightCity()

        # get the current plot
        plot = CyInterface().getMouseOverPlot()
        x = plot.getX()
        y = plot.getY()

        # get the current player
        pPlayer = gc.getPlayer(PlayerUtil.getActivePlayerID())
        if not pPlayer or pPlayer.isNone():
            BugUtil.warn("CvDotMapOverlayScreen.onMouseOverPlot() was passed an invalid player id: %s" % (str(ePlayer)))
            return False
        eTeam = pPlayer.getTeam()

        # update city location if plot is visible
        if plot.isRevealed(eTeam, False):
            self.currentPoint = (x, y)
            g_DotMap.highlightCity(self.currentPoint, self.currentColor)
            self.resetInterfaceMode()
    
    def resetInterfaceMode(self):
        if CyInterface().getInterfaceMode() != InterfaceModeTypes.INTERFACEMODE_PYTHON_PICK_PLOT:
            CyInterface().setInterfaceMode(InterfaceModeTypes.INTERFACEMODE_PYTHON_PICK_PLOT)
