/*
 *     Copyright 2010 Jean-Paul Balabanian and Yngve Devik Hammersland
 *
 *     This file is part of glsl4idea.
 *
 *     Glsl4idea is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as
 *     published by the Free Software Foundation, either version 3 of
 *     the License, or (at your option) any later version.
 *
 *     Glsl4idea is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with glsl4idea.  If not, see <http://www.gnu.org/licenses/>.
 */

package glslplugin.intentions.vectorcomponents;

import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.psi.PsiElement;
import com.intellij.ui.components.JBList;
import com.intellij.util.ThrowableRunnable;
import glslplugin.intentions.Intentions;
import glslplugin.lang.elements.GLSLIdentifier;
import glslplugin.util.VectorComponents;
import org.jetbrains.annotations.NotNull;

import static glslplugin.intentions.vectorcomponents.VectorComponentsPredicate.*;

public class VectorComponentsIntention extends Intentions {

    private static final Logger LOG = Logger.getInstance(VectorComponentsIntention.class);

    public VectorComponentsIntention() {
        super(new VectorComponentsPredicate());
    }

    @NotNull
    @Override
    public String getText() {
        return "Convert vector components";
    }

    @NotNull
    public String getFamilyName() {
        return "GLSL vector components";
    }

    protected void processIntention(PsiElement psiElement) {
        GLSLIdentifier elementTemp = null;
        if(psiElement instanceof GLSLIdentifier){
            elementTemp = (GLSLIdentifier) psiElement;
        }else{
            PsiElement parent = psiElement.getParent();
            if(parent instanceof GLSLIdentifier){
                elementTemp = (GLSLIdentifier) parent;
            }
        }
        if(elementTemp == null){
            Logger.getInstance(VectorComponentsIntention.class).warn("Could not find GLSLIdentifier for psiElement: "+psiElement);
            return;
        }
        final GLSLIdentifier element = elementTemp;

        String components = element.getText();

        final String[] results = createComponentVariants(components);

        String[] variants = new String[]{components + " -> " + results[0], components + " -> " + results[1]};
        //http://www.jetbrains.net/devnet/message/5208622#5208622
        final JBList<String> list = new JBList<>(variants);
        PopupChooserBuilder builder = new PopupChooserBuilder(list);
        builder.setTitle("Select Variant");
        builder.setItemChoosenCallback(new Runnable() {
            public void run() {
                try {
                    WriteCommandAction.writeCommandAction(element.getProject(), element.getContainingFile()).run(new ThrowableRunnable<Throwable>() {
                        @Override
                        public void run() {
                            replaceIdentifierElement(element, results[list.getSelectedIndex()]);
                        }
                    });
                } catch (Throwable t) {
                    LOG.error("replaceIdentifierElement failed", t);
                }
            }
        });
        JBPopup popup = builder.createPopup();
        popup.showInBestPositionFor(getEditor());
    }

    private String[] createComponentVariants(String components) {
        String[] results = new String[2];
        int i = 0;
        if (!rgba.matcher(components).matches()) {
            results[i++] = convertComponents(components, VectorComponents.RGBA);
        }

        if (!xyzw.matcher(components).matches()) {
            results[i++] = convertComponents(components, VectorComponents.XYZW);
        }

        if (!stpq.matcher(components).matches()) {
            results[i++] = convertComponents(components, VectorComponents.STPQ);
        }

        if (i != 2) {
            throw new RuntimeException("Unknown components!");
        }
        return results;
    }

    private String convertComponents(String vectorComponents, VectorComponents components) {
        return toComponents(toNumbers(vectorComponents), components);
    }

    private String toNumbers(String components) {
        String results = components.replaceAll("[rsx]", "1");
        results = results.replaceAll("[gty]", "2");
        results = results.replaceAll("[bpz]", "3");
        results = results.replaceAll("[aqw]", "4");
        return results;
    }

    private String toComponents(String componentsAsNumbers, VectorComponents components) {
        String results = componentsAsNumbers.replaceAll("1", components.getComponent(0));
        results = results.replaceAll("2", components.getComponent(1));
        results = results.replaceAll("3", components.getComponent(2));
        results = results.replaceAll("4", components.getComponent(3));
        return results;
    }
}