/*
 * 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.frames.mainframe.impl;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Widget;
import com.queplix.core.client.app.vo.FocusMeta;
import com.queplix.core.client.app.vo.MetaData;
import com.queplix.core.client.app.vo.SubFocusMeta;
import com.queplix.core.client.common.StringUtil;
import com.queplix.core.client.common.event.Event;
import com.queplix.core.client.common.event.EventListener;
import com.queplix.core.client.common.ui.ButtonData;
import com.queplix.core.client.common.ui.ButtonSet;
import com.queplix.core.client.common.ui.LabelButtonSet;
import com.queplix.core.client.common.ui.QTabBar;

/**
 * SubFocuses panel for MainFrameSA
 *
 * @author Vasily Mikhailitchenko
 * @since: 6 Dec 2006
 */
// TODO: once generics enabled, remove all occurences of '/*]' and '[*/'
class SubFocusesPanel extends ButtonSet implements EventListener {
    // -------------------- public events ------------------------
    public static interface Events {
        /**
         * Subfocus select event.
         * Event data passed along with it is of type SubFocusMeta.Index
         */
        Event/*]<SubFocusMeta.Index>[*/ SUBFOCUS_SELECTED
                = MainTree.Events.SUBFOCUS_SELECTED;
        Event MOUSE_LEFT = new Event();
    }
    // ----------------- end of public events --------------------

    private static final String STYLE_LABEL = "subFocus_label";
    private static final String STYLE_HIGHLIGHTED_LABEL
            = "subFocus_labelHighlighted";
    private static final String STYLE_SELECTED_LABEL = "subFocus_labelSelected";
    private static final int HEIGHT = 22;

    private DeckPanel deckPanel = new DeckPanel();
    private LabelButtonSet[] labelButtonSets;

    private FocusMeta.Index activatedFocus = null;
    private SubFocusMeta.Index[] activatedSubFocuses;

    private SubFocusMeta.Index lastSelectedSubFocus = null;

    public SubFocusesPanel(MetaData appMetaData) {
        FocusMeta[] focusesMeta = appMetaData.getFocuses();
        labelButtonSets = new LabelButtonSet[focusesMeta.length];

        initActivatedSubFocuses(focusesMeta.length);

        for(int i = 0; i < focusesMeta.length; i++) {
            labelButtonSets[i] = new LabelButtonSet(true);
            SubFocusMeta[] subfocuses = focusesMeta[i].getSubFocuses();
            for(int j = 0, m = subfocuses.length; j < m; j++) {
                SubFocusMeta sfm = subfocuses[j];
                Event event = new Event(sfm.getIndex());
                ButtonData data = new ButtonData(sfm.getCaption());
                data.setCaptionSelectedStyle(STYLE_SELECTED_LABEL);
                data.setCaptionHoverStyle(STYLE_HIGHLIGHTED_LABEL);
                labelButtonSets[i].addButton(event, data);
            }
            subscribeEvents(labelButtonSets[i]);
            deckPanel.add(labelButtonSets[i]);
        }
        if(focusesMeta.length > 0) {
            deckPanel.showWidget(0);
        }
        deckPanel.setHeight(StringUtil.pixelToSize(HEIGHT));
        initWidget(deckPanel);

        activateFocus(focusesMeta[0].getIndex());
    }

    public void activateFocus(FocusMeta.Index index) {
        activatedFocus = index;
        showActiveFocusSubFocuses();
        activateSubFocus(activatedSubFocuses[index.focus]);
    }

    public void activateSubFocus(SubFocusMeta.Index index) {
        if(activatedFocus != (FocusMeta.Index) index) {
            activateFocus((FocusMeta.Index) index);
        }
        selectSubFocus(index);
        activatedSubFocuses[index.focus] = index;
    }

    public void showActiveFocusSubFocuses() {
        if(activatedFocus != null) {
            showFocusSubFocuses(activatedFocus);
        } else {
            showFocusSubFocuses(0);
        }
    }

    public void showFocusSubFocuses(FocusMeta.Index index) {
        showFocusSubFocuses(index.focus);
    }

    private void showFocusSubFocuses(int index) {
        deckPanel.showWidget(index);
    }

    private void subscribeEvents(LabelButtonSet labelButtonSet) {
        labelButtonSet.addMouseListener(new MouseListenerAdapter() {
            public void onMouseLeave(Widget sender) {
                showActiveFocusSubFocuses();
                getEventSource().fireEvent(Events.MOUSE_LEFT);
            }
        });
        labelButtonSet.getEventSource().addEventListener(this);
    }

    public void onEvent(Event event, Widget sender) {
        SubFocusMeta.Index data = (SubFocusMeta.Index) event.getData();
        Event newEvent = Events.SUBFOCUS_SELECTED;
        newEvent.setData(data);
        newEvent.setUserGenerated(event.isUserGenerated());
        getEventSource().fireEvent(newEvent);
        activateSubFocus(data);
    }

    /**
     * Highlights some particular label,
     * de-highlights the previously highlighted one
     */
    private void selectSubFocus(SubFocusMeta.Index index) {
        if(lastSelectedSubFocus != null) {
            ((Widget) labelButtonSets[lastSelectedSubFocus.focus].getWidget(
                    lastSelectedSubFocus.subFocus)).setStyleName(STYLE_LABEL);
        }
        ((Widget) labelButtonSets[index.focus].getWidget(index.subFocus))
                .setStyleName(STYLE_SELECTED_LABEL);
        lastSelectedSubFocus = index;
    }

    private void initActivatedSubFocuses(int length) {
        activatedSubFocuses = new SubFocusMeta.Index[length];
        for(int i = 0; i < length; i++) {
            activatedSubFocuses[i] = new SubFocusMeta.Index();
            activatedSubFocuses[i].focus = i;
            activatedSubFocuses[i].subFocus = 0;
        }
    }

    public void adjustItemsPositions(QTabBar tabBar) {
        for(int i = 0; i < tabBar.getTabCount(); i++) {
            LabelButtonSet lbs = labelButtonSets[i];
            DOM.setStyleAttribute(lbs.getElement(), "paddingLeft",
                    StringUtil.pixelToSize(tabBar.getTabOffsetLeft(i)));
        }
    }
    

}
