/**
 * This software was developed and / or modified by Raytheon Company,
 * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
 * 
 * U.S. EXPORT CONTROLLED TECHNICAL DATA
 * This software product contains export-restricted data whose
 * export/transfer/disclosure is restricted by U.S. law. Dissemination
 * to non-U.S. persons whether in the United States or abroad requires
 * an export license or other authorization.
 * 
 * Contractor Name:        Raytheon Company
 * Contractor Address:     6825 Pine Street, Suite 340
 *                         Mail Stop B8
 *                         Omaha, NE 68106
 *                         402.291.0100
 * 
 * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
 * further licensing information.
 **/
package com.raytheon.viz.xdat;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;

/**
 * This class displays the Edit Data dialog.
 * 
 * <pre>
 * SOFTWARE HISTORY
 * Date         Ticket#    Engineer    Description
 * ------------ ---------- ----------- --------------------------
 * 10 Nov 2008             lvenable    Initial creation.
 * 10 Feb 2009             wkwock      Added functions.
 * Nov 29 2010             lbousaidi   fix a bug generated by Edit dialog
 * 04 Aug 2016  5800       mduff       Fixed use of time zones and regular expression.
 * 12 Mar 2018  DCS18260   astrakovsky Auto-refresh XDAT GUI after update.
 * 
 * </pre>
 * 
 * @author lvenable
 * 
 */
public class XdatEditDataDlg extends CaveSWTDialog {

    /**
     * Label containing the current value.
     */
    private Label currentValLbl;

    /**
     * New value text control.
     */
    private Text newValueTF;

    /**
     * AppsDefaults instance
     */
    private final AppsDefaults appsDefaults;

    /**
     * Database manager class.
     */
    private final XdatDB databaseMgr;

    /**
     * Main Dialog
     */
    private final ITextDisplay displayCB;

    /**
     * object for decode highlighted-message
     */
    XdatMessageDecoder msgDecoder;

    /**
     * Constructor.
     * 
     * @param parentShell
     *            Parent shell.
     */
    public XdatEditDataDlg(Shell parentShell, ITextDisplay displayCB, XdatDB databaseMgr) {
        super(parentShell, SWT.DIALOG_TRIM | SWT.RESIZE);
        setText("Edit Data");

        this.appsDefaults = AppsDefaults.getInstance();
        this.databaseMgr = databaseMgr;
        this.displayCB = displayCB;
        msgDecoder = new XdatMessageDecoder(displayCB.getSelectedText());
    }

    @Override
    protected Layout constructShellLayout() {
        return new GridLayout(1, false);
    }

    @Override
    protected void initializeComponents(Shell shell) {
        setReturnValue(false);
        createCurrentValueControls();

        // Add a horizontal separator bar
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        Label sepLbl = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
        sepLbl.setLayoutData(gd);

        createNewValueControls();

        createBottomButtons();
    }

    @Override
    protected void preOpened() {
        shell.setMinimumSize(shell.getBounds().width, shell.getBounds().height);
    }

    @Override
    protected boolean shouldOpen() {
        if (msgDecoder.hasDecodedMessages() == false) {
            MessageBox mb = new MessageBox(getParent(), SWT.ICON_WARNING | SWT.OK);
            mb.setText("Error");
            mb.setMessage("ERROR: No valid data lines were highlighted.");
            mb.open();
            setReturnValue(null);
            return false;
        }
        return true;
    }

    /**
     * Create the current value controls.
     */
    private void createCurrentValueControls() {
        Composite currValComp = new Composite(shell, SWT.NONE);
        currValComp.setLayout(new GridLayout(2, false));

        Label currValLbl = new Label(currValComp, SWT.NONE);
        currValLbl.setText("Current Value: ");

        GridData gd = new GridData(100, SWT.DEFAULT);
        currentValLbl = new Label(currValComp, SWT.NONE);
        currentValLbl.setLayoutData(gd);
        if (displayCB.getSelectedText().size() > 1) {
            currValLbl.setText("Values Selected: ");
            currentValLbl.setText(displayCB.getSelectedText().size() + "");
        } else {
            currentValLbl.setText(String.valueOf(msgDecoder.getDecodedMessages().get(0).getValue()));
        }
    }

    /**
     * Create the new value controls.
     */
    private void createNewValueControls() {
        GridLayout gl = new GridLayout(2, false);
        gl.verticalSpacing = 15;
        Composite newValComp = new Composite(shell, SWT.NONE);
        newValComp.setLayout(gl);

        // -----------------------------------------
        // Create a button composite
        // -----------------------------------------
        GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
        gd.horizontalSpan = 2;
        Composite buttonComp = new Composite(newValComp, SWT.NONE);
        buttonComp.setLayout(new GridLayout(2, false));
        buttonComp.setLayoutData(gd);

        gd = new GridData(110, SWT.DEFAULT);
        Button setMissingBtn = new Button(buttonComp, SWT.PUSH);
        setMissingBtn.setText("Set Missing");
        setMissingBtn.setLayoutData(gd);
        setMissingBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                newValueTF.setText("M");
            }
        });

        gd = new GridData(110, SWT.DEFAULT);
        Button setZeroBtn = new Button(buttonComp, SWT.PUSH);
        setZeroBtn.setText("Set to Zero");
        setZeroBtn.setLayoutData(gd);
        setZeroBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                newValueTF.setText("0.00");
            }
        });

        gd = new GridData(SWT.FILL, SWT.CENTER, false, true);
        Label newValLbl = new Label(newValComp, SWT.RIGHT);
        newValLbl.setText("New Value:");
        newValLbl.setLayoutData(gd);

        gd = new GridData(150, SWT.DEFAULT);
        newValueTF = new Text(newValComp, SWT.BORDER);
        newValueTF.setLayoutData(gd);
    }

    /**
     * Create the Post Data and Close buttons at the bottom of the display.
     */
    private void createBottomButtons() {
        GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
        Composite mainButtonComp = new Composite(shell, SWT.NONE);
        mainButtonComp.setLayout(new GridLayout(2, true));
        mainButtonComp.setLayoutData(gd);

        gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
        gd.widthHint = 100;
        Button postDataBtn = new Button(mainButtonComp, SWT.PUSH);
        postDataBtn.setText("Post Data");
        postDataBtn.setLayoutData(gd);
        postDataBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                postData();
            }

        });

        gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
        gd.widthHint = 100;
        Button closeBtn = new Button(mainButtonComp, SWT.PUSH);
        closeBtn.setText("Close");
        closeBtn.setLayoutData(gd);
        closeBtn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                shell.dispose();
            }
        });
    }

    /**
     * Post data to file in $shefdecode_input and to database in rejecteddata
     * table
     */
    protected void postData() {

        String newValue = newValueTF.getText().trim();

        /*
         * If the new value is not 'M' then parse the string to verify it is a
         * value number.
         */
        if (!newValue.equalsIgnoreCase("M")) {
            if (!newValue.matches("^[+-]?\\d*\\.?\\d*")) {
                MessageBox mb = new MessageBox(getParent(), SWT.ICON_WARNING | SWT.OK);
                mb.setMessage("Please enter a valid numeric value.");
                mb.open();
                return;
            }
        }

        XdatShefUtil shefUtil = new XdatShefUtil();
        shefUtil.createEditFile(msgDecoder.getDecodedMessages(), databaseMgr, newValue);
        shefUtil.sendFile();

        updateRejectedTable();

        // update the text area immediately with the value
        displayCB.updateTextAreaValue(newValue);

        shell.dispose();
    }

    /**
     * update rejecteddata table
     */
    public void updateRejectedTable() {

        for (DecodedMessage decodedMsg : msgDecoder.getDecodedMessages()) {
            Calendar obsTime = decodedMsg.getObsTime();
            SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
            dateFmt.setTimeZone(TimeUtil.GMT_TIME_ZONE);
            String validtime = dateFmt.format(obsTime.getTime());
            String user_id = appsDefaults.getToken("LOGNAME").toUpperCase();
            String newValue = newValueTF.getText().trim();

            databaseMgr.updateRejecteddata(decodedMsg.getId(), decodedMsg.getPe(), decodedMsg.getDur(),
                    decodedMsg.getTS(), decodedMsg.getExtremum(), decodedMsg.getValue(), validtime, newValue, user_id);
        }
    }
}
