/*
 * Copyright © 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.drumkit.components;

import com.nokia.example.drumkit.helpers.ImageLoader;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class Button {
    private final Image pressedImg;
    private final Image unpressedImg;
    private final Image disabledImg;
    private Rectangle boundingBox;
    private boolean pressed = false;
    private boolean enabled = true;
    private boolean selectable = false;
    private boolean selected = false;
    private boolean visible = true;
    private final Listener listener;

    /**
     * Interface for button listener. 
     */
    public interface Listener {
        void clicked(Button button);
    }

    /**
     * Constructor
     * @param unpressedImageUrl
     * @param pressedImageUrl
     * @param disabledImageUrl
     * @param listener
     */
    public Button(String unpressedImageUrl,
                  String pressedImageUrl,
                  String disabledImageUrl,
                  Listener listener)
    {
        this.listener = listener;
        unpressedImg = ImageLoader.loadImage(unpressedImageUrl);
        pressedImg = ImageLoader.loadImage(pressedImageUrl);
        disabledImg = ImageLoader.loadImage(disabledImageUrl);
        boundingBox = new Rectangle(0, 0, unpressedImg.getWidth(), unpressedImg.getHeight());
    }

    /**
     * Render the button
     * @param g
     */
    public void paint(Graphics g) {
        if (!visible) {
            return;
        }
        if (!enabled) {
            g.drawImage(disabledImg, boundingBox.getX(), boundingBox.getY(),
                        Graphics.TOP | Graphics.LEFT);
        }
        else if (pressed || selected) {
            g.drawImage(pressedImg, boundingBox.getX(), boundingBox.getY(),
                        Graphics.TOP | Graphics.LEFT);
        }
        else {
            g.drawImage(unpressedImg, boundingBox.getX(), boundingBox.getY(),
                        Graphics.TOP | Graphics.LEFT);
        }
    }

    /**
     * Set the position of top left coordinate of the button
     * @param x
     * @param y
     */
    public void setPosition(int x, int y) {
        boundingBox.setX(x);
        boundingBox.setY(y);
    }

    /**
     * Handle pressed events
     * @param x
     * @param y
     */
    public void pointerPressed(int x, int y) {
        if (!enabled) {
            return;
        }
        
        pressed = contains(x, y);
    }

    /**
     * Handle dragged events
     * @param x
     * @param y
     */
    public void pointerDragged(int x, int y) {
        pointerPressed(x, y);
    }

    /**
     * Handle released events
     * @param x
     * @param y
     */
    public void pointerReleased(int x, int y) {
        if (!enabled) {
            return;
        }
        
        if (pressed && contains(x, y)) {
            if (selectable) {
                selected = !selected;
            }
            
            listener.clicked(this);
        }
        
        pressed = false;
    }

    /**
     * Check wheter a point is inside the bounding box of the button
     * @param x
     * @param y
     */
    public boolean contains(int x, int y) {
        return boundingBox.contains(x, y);
    }

    public int getWidth() {
        return boundingBox.getWidth();
    }

    public int getHeight() {
        return boundingBox.getHeight();
    }

    public void enable() {
        enabled = true;
    }

    public void disable() {
        enabled = false;
    }

    public boolean isEnabled() {
        return enabled;
    }
    
    public void setVisible(boolean visible) {
        this.visible = visible;
    }
    
    public boolean isVisible() {
        return visible;
    }

    public int getX() {
        return boundingBox.getX();
    }

    public void setX(int x) {
        boundingBox.setX(x);
    }

    public int getY() {
        return boundingBox.getY();
    }

    public void setY(int y) {
        boundingBox.setY(y);
    }

    /**
     * @return True if button can be toggled
     */
    public boolean isSelectable() {
        return selectable;
    }

    /**
     * Determine whether button can be toggled between two states
     * @param selectable
     */
    public void setSelectable(boolean selectable) {
        this.selectable = selectable;
    }

    public boolean isSelected() {
        return selected;
    }

    /**
     * Select the button manually
     */
    public void select() {
        selectable = true;
        selected = true;
    }

    /**
     * Deselect the button manually
     */
    public void deselect() {
        selected = false;
    }

    protected boolean isPressed() {
        return pressed;
    }

    protected void setPressed(boolean pressed) {
        this.pressed = pressed;
    }

    protected Image getDisabledImage() {
        return disabledImg;
    }

    protected Image getPressedImage() {
        return pressedImg;
    }

    protected Image getUnpressedImage() {
        return unpressedImg;
    }
}
