
from __future__ import print_function

from LUIObject import LUIObject
from LUISprite import LUISprite
from LUILayouts import LUICornerLayout
from LUIInitialState import LUIInitialState
from LUIScrollableRegion import LUIScrollableRegion
from panda3d.core import Vec2

__all__ = ["LUIFrame"]


class LUIFrame(LUIObject):

    """ A container which can store multiple ui-elements. If you don't want a
    border/background, you should use an empty LUIObject as container instead.
    """

    FS_sunken = 1
    FS_raised = 2

    def __init__(self, inner_padding=5, scrollable=False, style=FS_raised,
                 **kwargs):
        """ Creates a new frame with the given options and style. If scrollable
        is True, the contents of the frame will scroll if they don't fit into
        the frame height. inner_padding only has effect if scrollable is True.
        You can call fit_to_children() to make the frame fit automatically to
        it's contents."""
        LUIObject.__init__(self)

        # Each *style* has a different border size (size of the shadow). The
        # border size shouldn't get calculated to the actual framesize, so we
        # are determining it first and then substracting it.
        # TODO: We could do this automatically, determined by the sprite size
        # probably?
        self._border_size = 0
        self.padding = 10
        self.solid = True
        prefix = ""

        if style == LUIFrame.FS_raised:
            temp = LUISprite(self, "Frame_Left", "skin")
            self._border_size = temp.width
            self.remove_child(temp)
            prefix = "Frame_"
        elif style == LUIFrame.FS_sunken:
            self._border_size = 0
            prefix = "SunkenFrame_"
        else:
            raise Exception("Unkown LUIFrame style: " + style)

        LUIInitialState.init(self, kwargs)

        self._scrollable = scrollable
        self._layout = LUICornerLayout(parent=self, image_prefix=prefix)
        self._layout.margin = -(self.padding.top + self._border_size)
        if self._scrollable:
            self._content = LUIObject(self)
            self._content.size = Vec2(self.width, self.height)
            self._content.pos = (self._border_size, self._border_size)
            self._scroll_content = LUIScrollableRegion(
                self._content,
                width=self.width - 2 * self.padding.left,
                height=self.height - 2 * self.padding.left,
                padding=inner_padding)
            self.content_node = self._scroll_content.content_node


    def hasMouse(self):
        if not self.visible: return False
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            mousePos = (mpos.getX() * base.getAspectRatio(), mpos.getY())

            screenWidth = base.win.getProperties().getXSize()
            screenHeight = base.win.getProperties().getYSize()
            ratio = base.getAspectRatio()

            relLeft = -ratio
            relTop = 1

            zeroXPx = screenWidth / 2
            zeroZPx = screenHeight / 2

            objWidth = self.get_width()
            objHeight = self.get_height()

            objX, objZ = [0,0]

            if self.center_horizontal:
                objX = zeroXPx - (objWidth / 2)
            else:
                objX = self.pos[0]
                objX += self.margin.left

            if self.center_vertical:
                objZ = zeroZPx - (objHeight / 2)
            else:
                objZ = self.pos[1]
                objZ += self.margin.top

            oneUnitPerPixelX = ratio / zeroXPx
            oneUnitPerPixelZ = 1 / zeroZPx

            left = relLeft + (oneUnitPerPixelX * objX)
            top = relTop - (oneUnitPerPixelZ * objZ)

            right = left + (oneUnitPerPixelX * objWidth)
            bottom = top - (oneUnitPerPixelZ * objHeight)

            if (mousePos[0] <= right # Right
            and mousePos[0] >= left # Left
            and mousePos[1] >= bottom # Bottom
            and mousePos[1] <= top): # Top
                return True
            return False
        return False
