/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.queplix.core.client.common.ui;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.ClickListenerCollection;
import com.google.gwt.user.client.ui.SourcesClickEvents;
import com.google.gwt.user.client.ui.Widget;

/**
 * Represents "area" html element
 *
 * @author Michael Trofimov
 */
public class ImageMapArea extends Widget implements SourcesClickEvents {

    private static String[] shapePossibleValues = new String[]{
            "circ",
            "circle",
            "poly",
            "polygon",
            "rect",
            "rectangle"
    };

    private ClickListenerCollection clickListeners;

    private String targetHistoryToken;


    private ImageMapArea() {
        setElement(DOM.createElement("area"));
        setupNativeClickListener(getElement());
    }

    ImageMapArea(String shape, String coords) {
        this();
        setShape(shape);
        setCoords(coords);
    }

    ImageMapArea(String shape, String coords, String targetHistoryToken) {
        this(shape, coords);
        setTargetHistoryToken(targetHistoryToken);
    }

    public String getShape() {
        return DOM.getAttribute(this.getElement(), "shape");
    }

    public String getCoords() {
        return DOM.getAttribute(this.getElement(), "coords");
    }

    public void addClickListener(ClickListener listener) {
        if(clickListeners == null) {
            clickListeners = new ClickListenerCollection();
        }

        clickListeners.add(listener);
    }

    public void removeClickListener(ClickListener listener) {
        if(clickListeners != null) {
            clickListeners.remove(listener);
        }
    }

    /**
     * Gets the history token referenced by this widget.
     *
     * @return the target history token
     * @see #setTargetHistoryToken
     */
    public String getTargetHistoryToken() {
        return targetHistoryToken;
    }

    /**
     * Sets the history token referenced by this widget. This is the history
     * token that will be passed to {@link History#newItem} when this link is
     * clicked.
     *
     * @param targetHistoryToken the new target history token
     */
    public void setTargetHistoryToken(String targetHistoryToken) {
        this.targetHistoryToken = targetHistoryToken;
        DOM.setAttribute(this.getElement(), "href", "#" + targetHistoryToken);
    }

    // ---------------------------------------------------------------------- Non-public methods

    private native void setupNativeClickListener(Element elem) /*-{
        var self = this;
        elem.onclick = function(){
            self.@com.queplix.core.client.common.ui.ImageMapArea::fireClick()();
        };
    }-*/;

    private native void cleanNativeClickListener(Element elem) /*-{
        elem.onclick = null;
    }-*/;

    /**
     * Non-javadoc
     *
     * @see #setupNativeClickListener(Element)
     */
    private void fireClick() {
        if(clickListeners != null) {
            clickListeners.fireClick(this);
        }

        if(targetHistoryToken != null) {
            History.newItem(targetHistoryToken);
        }
    }

    /**
     * Clear out the element's native onclick listener (breaking the circular
     * reference between it and the widget).
     */
    protected void onDetach() {
        cleanNativeClickListener(getElement());
        super.onDetach();
    }

    protected void setShape(String shape) {
        if(shape == null) {
            throw new IllegalArgumentException(
                    "Parameter 'shape' cannot be a null");
        }

        boolean match = false;
        for(int i = 0; i < shapePossibleValues.length; i++) {
            if(shape.equalsIgnoreCase(shapePossibleValues[i])) {
                match = true;
                break;
            }
        }
        if(!match) {
            throw new IllegalArgumentException(
                    "Illegal value of 'shape' parameter");
        }

        DOM.setAttribute(this.getElement(), "shape", shape);
    }

    protected void setCoords(String coords) {
        if(coords == null) {
            throw new IllegalArgumentException(
                    "Parameter 'coords' cannot be a null");
        }

        DOM.setAttribute(this.getElement(), "coords", coords);
    }

}
