/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * 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.haulmont.cuba.web.widgets.client.notification;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.VNotification;

import static com.haulmont.cuba.web.widgets.client.appui.CubaUIConnector.CUBA_NOTIFICATION_MODALITY_CURTAIN;

public class CubaNotification extends VNotification {
    public static final String TRAY_STYLE = "tray";

    public static final int MARGIN_SIZE = 10;

    @Override
    public boolean onEventPreview(Event event) {
        int type = DOM.eventGetType(event);

        if ((type == Event.ONCLICK || type == Event.ONTOUCHEND)
                && event.getEventTarget() != null) {
            Element target = Element.as(event.getEventTarget());
            if (target.getClassName() != null && target.getClassName().contains(CUBA_NOTIFICATION_MODALITY_CURTAIN)) {
                hide();
                return false;
            }
        }

        if (type == Event.ONKEYDOWN && event.getKeyCode() == KeyCodes.KEY_ESCAPE) {
            if (!getElement().getClassName().contains(TRAY_STYLE)) {
                hide();
                return false;
            }
        }

        return super.onEventPreview(event);
    }

    @Override
    protected void beforeAddNotificationToCollection() {
        for (int i = NOTIFICATIONS.size() - 1; i >= 0; i--) {
            final Element el = NOTIFICATIONS.get(i).getElement();
            if (el.hasClassName("v-position-bottom") && el.hasClassName(TRAY_STYLE)) {
                int notificationPosition = 0;
                try {
                    notificationPosition = Integer.valueOf(el.getStyle()
                            .getBottom().replace("px", ""))
                            + WidgetUtil.getRequiredHeight(getElement());
                } catch (NumberFormatException nex) {
                    notificationPosition += WidgetUtil
                            .getRequiredHeight(getElement());
                }

                notificationPosition += (i == NOTIFICATIONS.size() - 1) ? (2 * MARGIN_SIZE) : MARGIN_SIZE;
                el.getStyle().setPropertyPx("bottom", notificationPosition);
            }
        }
    }

    @Override
    protected void afterRemoveNotificationFromCollection(VNotification removedNotification, int removedIdx) {
        if (removedIdx == 0) {
            return;
        }

        Element removedElement = removedNotification.getElement();
        int removedElementHeight = WidgetUtil.getRequiredHeight(removedElement);
        for (int i = removedIdx - 1; i >= 0; i--) {
            Element el = NOTIFICATIONS.get(i).getElement();
            if (el.hasClassName("v-position-bottom") && el.hasClassName(TRAY_STYLE)) {
                int notificationPosition = 0;
                if (i == NOTIFICATIONS.size() - 1) {
                    notificationPosition = MARGIN_SIZE;
                } else {
                    try {
                        notificationPosition = Integer.valueOf(
                                el.getStyle().getBottom().replace("px", "")) - removedElementHeight;
                        notificationPosition -= MARGIN_SIZE;
                    } catch (NumberFormatException nex) {
                        //
                    }
                }
                el.getStyle().setPropertyPx("bottom", notificationPosition);
            }
        }
    }
}
@@ -2010,24 +2010,104 @@
 lection() %7B%0A
+        if (!isTrayNotification(getElement())) %7B%0A            return;%0A        %7D%0A%0A
         for 
@@ -2242,74 +2242,29 @@
 if (
-el.hasClassName(%22v-position-bottom%22) && el.hasClassName(TRAY_STYLE
+isTrayNotification(el
 )) %7B
@@ -2773,38 +2773,32 @@
  += 
-(i == NOTIFICATIONS.size() - 1
+isLastTrayNotification(i
 ) ? 
@@ -3183,32 +3183,114 @@
 n.getElement();%0A
+        if (!isTrayNotification(removedElement)) %7B%0A            return;%0A        %7D%0A%0A
         int remo
@@ -3486,74 +3486,29 @@
 if (
-el.hasClassName(%22v-position-bottom%22) && el.hasClassName(TRAY_STYLE
+isTrayNotification(el
 )) %7B
@@ -4171,10 +4171,572 @@
  %7D%0A    %7D
+%0A%0A    protected boolean isTrayNotification(Element element) %7B%0A        return element.hasClassName(%22v-position-bottom%22) && element.hasClassName(TRAY_STYLE);%0A    %7D%0A%0A    protected boolean isLastTrayNotification(int index) %7B%0A        int lastTrayIndex = 0;%0A        for (int i = NOTIFICATIONS.size() - 1; i %3E 0; i--) %7B%0A            Element notification = NOTIFICATIONS.get(i).getElement();%0A            if (isTrayNotification(notification)) %7B%0A                lastTrayIndex = i;%0A                break;%0A            %7D%0A        %7D%0A%0A        return lastTrayIndex == index;%0A    %7D
 %0A%7D

Implement notification stacking for TRAY NotificationType #344