/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.android.ide.eclipse.adt.internal.editors.layout.configuration;

import static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX;

import com.android.ide.eclipse.adt.internal.editors.Hyperlinks;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SubmenuAction;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo.ActivityAttributes;
import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
import com.android.sdklib.IAndroidTarget;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolItem;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Action which creates a submenu displaying available themes
 */
class ThemeMenuAction extends SubmenuAction {
    private static final String DEVICE_LIGHT_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX + "Theme.DeviceDefault.Light";  //$NON-NLS-1$
    private static final String HOLO_LIGHT_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX + "Theme.Holo.Light";           //$NON-NLS-1$
    private static final String DEVICE_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX + "Theme.DeviceDefault";        //$NON-NLS-1$
    private static final String HOLO_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX + "Theme.Holo";                 //$NON-NLS-1$
    private static final String LIGHT_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX +"Theme.Light";                 //$NON-NLS-1$
    private static final String THEME_PREFIX =
            ANDROID_STYLE_RESOURCE_PREFIX +"Theme";                       //$NON-NLS-1$

    // Constants used to indicate what type of menu is being shown, such that
    // the submenus can lazily construct their contents
    private static final int MENU_MANIFEST = 1;
    private static final int MENU_PROJECT = 2;
    private static final int MENU_THEME = 3;
    private static final int MENU_THEME_LIGHT = 4;
    private static final int MENU_HOLO = 5;
    private static final int MENU_HOLO_LIGHT = 6;
    private static final int MENU_DEVICE = 7;
    private static final int MENU_DEVICE_LIGHT = 8;
    private static final int MENU_ALL = 9;

    private final ConfigurationChooser mConfigChooser;
    private final List<String> mThemeList;
    /** Type of menu; one of the constants {@link #MENU_ALL} etc */
    private final int mType;

    ThemeMenuAction(int type, String title, ConfigurationChooser configuration,
            List<String> themeList) {
        super(title);
        mType = type;
        mConfigChooser = configuration;
        mThemeList = themeList;
    }

    static void showThemeMenu(ConfigurationChooser configChooser, ToolItem combo,
            List<String> themeList) {
        MenuManager manager = new MenuManager();

        // First show the currently selected theme (grayed out since you can't
        // reselect it)
        Configuration configuration = configChooser.getConfiguration();
        String currentTheme = configuration.getTheme();
        String currentName = null;
        if (currentTheme != null) {
            currentName = ResourceHelper.styleToTheme(currentTheme);
            SelectThemeAction action = new SelectThemeAction(configChooser,
                    currentName,
                    currentTheme,
                    true /* selected */);
            action.setEnabled(false);
            manager.add(action);
            manager.add(new Separator());
        }

        String preferred = configuration.computePreferredTheme();
        if (preferred != null && !preferred.equals(currentTheme)) {
            manager.add(new SelectThemeAction(configChooser,
                    ResourceHelper.styleToTheme(preferred),
                    preferred, false /* selected */));
            manager.add(new Separator());
        }

        IAndroidTarget target = configuration.getTarget();
        int apiLevel = target != null ? target.getVersion().getApiLevel() : 1;
        boolean hasHolo = apiLevel >= 11;   // Honeycomb
        boolean hasDeviceDefault = apiLevel >= 14; // ICS

        // TODO: Add variations of the current theme here, e.g.
        // if you're using Theme.Holo, add Theme.Holo.Dialog, Theme.Holo.Panel,
        // Theme.Holo.Wallpaper etc

        manager.add(new ThemeMenuAction(MENU_PROJECT, "Project Themes",
                configChooser, themeList));
        manager.add(new ThemeMenuAction(MENU_MANIFEST, "Manifest Themes",
                configChooser, themeList));

        manager.add(new Separator());

        if (hasHolo) {
            manager.add(new ThemeMenuAction(MENU_HOLO, "Holo",
                    configChooser, themeList));
            manager.add(new ThemeMenuAction(MENU_HOLO_LIGHT, "Holo.Light",
                    configChooser, themeList));
        }
        if (hasDeviceDefault) {
            manager.add(new ThemeMenuAction(MENU_DEVICE, "DeviceDefault",
                    configChooser, themeList));
            manager.add(new ThemeMenuAction(MENU_DEVICE_LIGHT, "DeviceDefault.Light",
                    configChooser, themeList));
        }
        manager.add(new ThemeMenuAction(MENU_THEME, "Theme",
                configChooser, themeList));
        manager.add(new ThemeMenuAction(MENU_THEME_LIGHT, "Theme.Light",
                configChooser, themeList));

        // TODO: Add generic types like Wallpaper, Dialog, Alert, etc here, with
        // submenus for picking it within each theme category?

        manager.add(new Separator());
        manager.add(new ThemeMenuAction(MENU_ALL, "All",
                configChooser, themeList));

        if (currentTheme != null) {
            assert currentName != null;
            manager.add(new Separator());
            String title = String.format("Open %1$s Declaration...", currentName);
            manager.add(new OpenThemeAction(title, configChooser.getEditedFile(), currentTheme));
        }

        Menu menu = manager.createContextMenu(configChooser.getShell());

        Rectangle bounds = combo.getBounds();
        Point location = new Point(bounds.x, bounds.y + bounds.height);
        location = combo.getParent().toDisplay(location);
        menu.setLocation(location.x, location.y);
        menu.setVisible(true);
    }

    @Override
    protected void addMenuItems(Menu menu) {
        switch (mType) {
            case MENU_ALL:
                addMenuItems(menu, mThemeList);
                break;

            case MENU_MANIFEST: {
                IProject project = mConfigChooser.getEditedFile().getProject();
                ManifestInfo manifest = ManifestInfo.get(project);
                Configuration configuration = mConfigChooser.getConfiguration();
                String activity = configuration.getActivity();
                if (activity != null) {
                    ActivityAttributes attributes = manifest.getActivityAttributes(activity);
                    if (attributes != null) {
                        String theme = attributes.getTheme();
                        if (theme != null) {
                            addMenuItem(menu, theme, isSelectedTheme(theme));
                        }
                    }
                }

                String manifestTheme = manifest.getManifestTheme();
                boolean found = false;
                Set<String> allThemes = new HashSet<String>();
                if (manifestTheme != null) {
                    found = true;
                    allThemes.add(manifestTheme);
                }
                for (ActivityAttributes info : manifest.getActivityAttributesMap().values()) {
                    if (info.getTheme() != null) {
                        found = true;
                        allThemes.add(info.getTheme());
                    }
                }
                List<String> sorted = new ArrayList<String>(allThemes);
                Collections.sort(sorted);
                String current = configuration.getTheme();
                for (String theme : sorted) {
                    boolean selected = theme.equals(current);
                    addMenuItem(menu, theme, selected);
                }
                if (!found) {
                    addDisabledMessageItem("No themes are registered in the manifest");
                }
                break;
            }
            case MENU_PROJECT: {
                int size = mThemeList.size();
                List<String> themes = new ArrayList<String>(size);
                for (int i = 0; i < size; i++) {
                    String theme = mThemeList.get(i);
                    if (ResourceHelper.isProjectStyle(theme)) {
                        themes.add(theme);
                    }
                }
                if (themes.isEmpty()) {
                    addDisabledMessageItem("There are no local theme styles in the project");
                } else {
                    addMenuItems(menu, themes);
                }
                break;
            }
            case MENU_THEME: {
                // Can't just use the usual filterThemes() call here because we need
                // to exclude on multiple prefixes: Holo, DeviceDefault, Light, ...
                List<String> themes = new ArrayList<String>(mThemeList.size());
                for (String theme : mThemeList) {
                    if (theme.startsWith(THEME_PREFIX)
                            && !theme.startsWith(LIGHT_PREFIX)
                            && !theme.startsWith(HOLO_PREFIX)
                            && !theme.startsWith(DEVICE_PREFIX)) {
                        themes.add(theme);
                    }
                }

                addMenuItems(menu, themes);
                break;
            }
            case MENU_THEME_LIGHT:
                addMenuItems(menu, filterThemes(LIGHT_PREFIX, null));
                break;
            case MENU_HOLO:
                addMenuItems(menu, filterThemes(HOLO_PREFIX, HOLO_LIGHT_PREFIX));
                break;
            case MENU_HOLO_LIGHT:
                addMenuItems(menu, filterThemes(HOLO_LIGHT_PREFIX, null));
                break;
            case MENU_DEVICE:
                addMenuItems(menu, filterThemes(DEVICE_PREFIX, DEVICE_LIGHT_PREFIX));
                break;
            case MENU_DEVICE_LIGHT:
                addMenuItems(menu, filterThemes(DEVICE_LIGHT_PREFIX, null));
                break;
        }
    }

    private List<String> filterThemes(String include, String exclude) {
        List<String> themes = new ArrayList<String>(mThemeList.size());
        for (String theme : mThemeList) {
            if (theme.startsWith(include) && (exclude == null || !theme.startsWith(exclude))) {
                themes.add(theme);
            }
        }

        return themes;
    }

    private void addMenuItems(Menu menu, List<String> themes) {
        String current = mConfigChooser.getConfiguration().getTheme();
        for (String theme : themes) {
            addMenuItem(menu, theme, theme.equals(current));
        }
    }

    private boolean isSelectedTheme(String theme) {
        return theme.equals(mConfigChooser.getConfiguration().getTheme());
    }

    private void addMenuItem(Menu menu, String theme, boolean selected) {
        String title = ResourceHelper.styleToTheme(theme);
        SelectThemeAction action = new SelectThemeAction(mConfigChooser, title, theme, selected);
        new ActionContributionItem(action).fill(menu, -1);
    }

    private static class OpenThemeAction extends Action {
        private final String mTheme;
        private final IFile mFile;

        private OpenThemeAction(String title, IFile file, String theme) {
            super(title, IAction.AS_PUSH_BUTTON);
            mFile = file;
            mTheme = theme;
        }

        @Override
        public void run() {
            IProject project = mFile.getProject();
            IHyperlink[] links = Hyperlinks.getResourceLinks(null, mTheme, project, null);
            if (links != null && links.length > 0) {
                IHyperlink link = links[0];
                link.open();
            }
        }
    }
}
