package cz.fidentis.analyst.symmetry;

import cz.fidentis.analyst.core.ControlPanel;
import cz.fidentis.analyst.core.ControlPanelBuilder;
import org.openide.windows.WindowManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.vecmath.Point3d;

/**
 * Control panel for Polyline profiles and cutting planes
 *
 * @author Dominik Racek
 */
public class ProfilesPanel extends ControlPanel {

    /*
     * GUI primitives holding the configuration state:
     */
    private JTextField cuttingOffset;
    private JCheckBox alignProfiles;
    private JCheckBox showCuttingPlane;
    private PolylinePanel polylinePanel;
    private JCheckBox mirrorCuts;

    /*
     * Handled actions
     */
    public static final String ACTION_COMMAND_SHOW_HIDE_PLANE = "show-hide symmetry plane";
    public static final String ACTION_COMMAND_RECOMPUTE = "recompute";
    public static final String ACTION_COMMAND_EXPORT = "export";
    public static final String ACTION_OFFSET_CUTTING_PLANE = "offset_plane";
    public static final String ACTION_ALIGN_PROFILES = "align_profiles";
    public static final String ACTION_MIRROR_CUTS = "mirror-cuts";

    /*
     * Mandatory design elements
     */
    public static final String ICON = "profiles28x28.png";
    public static final String NAME = "Profiles";

    /**
     * Constructor for one face
     */
    public ProfilesPanel(ActionListener action, List<Point3d> values) {
        setName(NAME);

        ControlPanelBuilder builder = new ControlPanelBuilder(this);
        this.polylinePanel = new PolylinePanel(values);

        builder.addPolylinePanel(this.polylinePanel);
        builder.addLine();

        buildPanel(action, builder);
    }

    /**
     * Constructor for two faces
     */
    public ProfilesPanel(ActionListener action, List<Point3d> primary, List<Point3d> secondary) {
        setName(NAME);

        ControlPanelBuilder builder = new ControlPanelBuilder(this);
        this.polylinePanel = new PolylinePanel(primary, secondary);

        builder.addPolylinePanel(this.polylinePanel);
        builder.addLine();

        buildPanel(action, builder);
    }

    private void buildPanel(ActionListener action, ControlPanelBuilder builder) {
        builder.addCaptionLine("Computation options:");
        builder.addLine();

        cuttingOffset = builder.addSliderOptionLine(
                (ActionEvent e) -> {
                    showCuttingOffsetHelp();
                },
                "Cutting Plane Offset",
                -1,
                (ActionEvent e) -> {
                    action.actionPerformed(new ActionEvent(
                            e.getSource(),
                            ActionEvent.ACTION_PERFORMED,
                            ACTION_OFFSET_CUTTING_PLANE
                    ));
                });
        builder.addLine();

        showCuttingPlane = builder.addCheckBoxOptionLine(
                null,
                "Show cutting plane",
                true,
                createListener(action, ACTION_COMMAND_SHOW_HIDE_PLANE)
        );
        builder.addLine();

        mirrorCuts = builder.addCheckBoxOptionLine(
                null,
                "Mirror cuts",
                false,
                createListener(action, ACTION_MIRROR_CUTS)
        );
        builder.addLine();

        alignProfiles = builder.addCheckBoxOptionLine(
                null,
                "Align profiles",
                false,
                createListener(action, ACTION_ALIGN_PROFILES)
        );
        builder.addLine();

        builder.addButtons(
                List.of("Recompute",
                        "Export Profile(s)"),
                List.of(
                        (ActionEvent e) -> {
                            action.actionPerformed(new ActionEvent(
                                    e.getSource(),
                                    ActionEvent.ACTION_PERFORMED,
                                    ACTION_COMMAND_RECOMPUTE
                            ));
                        },
                        (ActionEvent e) -> {
                            action.actionPerformed(new ActionEvent(
                                    e.getSource(),
                                    ActionEvent.ACTION_PERFORMED,
                                    ACTION_COMMAND_EXPORT
                            ));
                        }
                )
        );
    }

    @Override
    public ImageIcon getIcon() {
        return getStaticIcon();
    }

    /**
     * Static implementation of the {@link #getIcon()} method.
     *
     * @return Control panel icon
     */
    public static ImageIcon getStaticIcon() {
        return new ImageIcon(ProfilesPanel.class.getClassLoader().getResource("/" + ICON));
    }

    private void showCuttingOffsetHelp() {
        JOptionPane.showMessageDialog(WindowManager.getDefault().findTopComponent("Cutting Plane Offset"),
                "TO DO",
                "TO DO",
                0,
                new ImageIcon(getClass().getResource("/distance.png"))
        );
    }

    public boolean isShowPlaneChecked() {
        return showCuttingPlane.isSelected();
    }

    public boolean isMirrorCutsChecked() {
        return mirrorCuts.isSelected();
    }

    public double getOffsetValue() {
        return ControlPanelBuilder.parseLocaleDouble(cuttingOffset);
    }

    /**
     * Sets the mirrorCuts boolean based on the checkbox
     */
    public void setMirrorCuts() {
        this.polylinePanel.setMirrorCuts(this.mirrorCuts.isSelected());
    }

    /**
     * Sets the alignProfiles boolean based on the checkbox
     */
    public void setAlignProfiles() {
        this.polylinePanel.setAlignProfiles(alignProfiles.isSelected());
    }

    /**
     * Sets the primary points in the polyline panel
     *
     * @param points primary points
     */
    public void setPrimaryPoints(List<Point3d> points) {
        this.polylinePanel.setPrimaryPoints(points);
    }

    /**
     * Sets the primary mirror points in the polyline panel
     *
     * @param points primary mirror points
     */
    public void setPrimaryMirrorPoints(List<Point3d> points) {
        this.polylinePanel.setPrimaryMirrorPoints(points);
    }

    /**
     * Sets the secondary points in the polyline panel
     *
     * @param points secondary points
     */
    public void setSecondaryPoints(List<Point3d> points) {
        this.polylinePanel.setSecondaryPoints(points);
    }

    /**
     * Sets the secondary mirror points in the polyline panel
     *
     * @param points secondary mirror points
     */
    public void setSecondaryMirrorPoints(List<Point3d> points) {
        this.polylinePanel.setSecondaryMirrorPoints(points);
    }

}