/*
 * Copyright (C) 2010 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.export;

import com.android.SdkConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper.ManifestSectionPart;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

/**
 * Section part for editing fields of a properties file in an Export editor.
 * <p/>
 * This base class is intended to be derived and customized.
 */
abstract class AbstractPropertiesFieldsPart extends ManifestSectionPart {

    private final HashMap<String, Control> mNameToField = new HashMap<String, Control>();

    private ExportEditor mEditor;

    private boolean mInternalTextUpdate = false;

    public AbstractPropertiesFieldsPart(Composite body, FormToolkit toolkit, ExportEditor editor) {
        super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */);
        mEditor = editor;
    }

    protected HashMap<String, Control> getNameToField() {
        return mNameToField;
    }

    protected ExportEditor getEditor() {
        return mEditor;
    }

    protected void setInternalTextUpdate(boolean internalTextUpdate) {
        mInternalTextUpdate = internalTextUpdate;
    }

    protected boolean isInternalTextUpdate() {
        return mInternalTextUpdate;
    }

    /**
     * Adds a modify listener to every text field that will mark the part as dirty.
     *
     * CONTRACT: Derived classes MUST call this at the end of their constructor.
     *
     * @see #setFieldModifyListener(Control, ModifyListener)
     */
    protected void addModifyListenerToFields() {
        ModifyListener markDirtyListener = new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                // Mark the part as dirty if a field has been changed.
                // This will force a commit() operation to store the data in the model.
                if (!mInternalTextUpdate) {
                    markDirty();
                }
            }
        };

        for (Control field : mNameToField.values()) {
            setFieldModifyListener(field, markDirtyListener);
        }
    }

    /**
     * Sets a listener that will mark the part as dirty when the control is modified.
     * The base method only handles {@link Text} fields.
     *
     * CONTRACT: Derived classes CAN use this to add a listener to their own controls.
     * The listener must call {@link #markDirty()} when the control is modified by the user.
     *
     * @param field A control previously registered with {@link #getNameToField()}.
     * @param markDirtyListener A {@link ModifyListener} that invokes {@link #markDirty()}.
     *
     * @see #isInternalTextUpdate()
     */
    protected void setFieldModifyListener(Control field, ModifyListener markDirtyListener) {
        if (field instanceof Text) {
            ((Text) field).addModifyListener(markDirtyListener);
        }
    }

    /**
     * Updates the model based on the content of fields. This is invoked when a field
     * has marked the document as dirty.
     *
     * CONTRACT: Derived classes do not need to override this.
     */
    @Override
    public void commit(boolean onSave) {

        // We didn't store any information indicating which field was dirty (we could).
        // Since there are not many fields, just update all the document lines that
        // match our field keywords.

        if (isDirty()) {
            mEditor.wrapRewriteSession(new Runnable() {
                @Override
                public void run() {
                    saveFieldsToModel();
                }
            });
        }

        super.commit(onSave);
    }

    private void saveFieldsToModel() {
        // Get a list of all keywords to process. Go thru the document, replacing in-place
        // the ones we can find and remove them from this set. This will leave the list
        // of new keywords to add at the end of the document.
        HashSet<String> allKeywords = new HashSet<String>(mNameToField.keySet());

        IDocument doc = mEditor.getDocument();
        int numLines = doc.getNumberOfLines();

        String delim = null;
        try {
            delim = numLines > 0 ? doc.getLineDelimiter(0) : null;
        } catch (BadLocationException e1) {
            // ignore
        }
        if (delim == null || delim.length() == 0) {
            delim = SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS ?
                    "\r\n" : "\n"; //$NON-NLS-1$ //$NON-NLS-2#
        }

        for (int i = 0; i < numLines; i++) {
            try {
                IRegion info = doc.getLineInformation(i);
                String line = doc.get(info.getOffset(), info.getLength());
                line = line.trim();
                if (line.startsWith("#")) {  //$NON-NLS-1$
                    continue;
                }

                int pos = line.indexOf('=');
                if (pos > 0 && pos < line.length() - 1) {
                    String key = line.substring(0, pos).trim();

                    Control field = mNameToField.get(key);
                    if (field != null) {

                        // This is the new line to inject
                        line = key + "=" + getFieldText(field);

                        try {
                            // replace old line by new one. This doesn't change the
                            // line delimiter.
                            mInternalTextUpdate = true;
                            doc.replace(info.getOffset(), info.getLength(), line);
                            allKeywords.remove(key);
                        } finally {
                            mInternalTextUpdate = false;
                        }
                    }
                }

            } catch (BadLocationException e) {
                // TODO log it
                AdtPlugin.log(e, "Failed to replace in export.properties");
            }
        }

        for (String key : allKeywords) {
            Control field = mNameToField.get(key);
            if (field != null) {
                // This is the new line to inject
                String line = key + "=" + getFieldText(field);

                try {
                    // replace old line by new one
                    mInternalTextUpdate = true;

                    numLines = doc.getNumberOfLines();

                    IRegion info = numLines > 0 ? doc.getLineInformation(numLines - 1) : null;
                    if (info != null && info.getLength() == 0) {
                        // last line is empty. Insert right before there.
                        doc.replace(info.getOffset(), info.getLength(), line);
                    } else {
                        if (numLines > 0) {
                            String eofDelim = doc.getLineDelimiter(numLines - 1);
                            if (eofDelim == null || eofDelim.length() == 0) {
                                // The document doesn't end with a line delimiter, so add
                                // one to the line to be written.
                                line = delim + line;
                            }
                        }

                        int len = doc.getLength();
                        doc.replace(len, 0, line);
                    }

                    allKeywords.remove(key);
                } catch (BadLocationException e) {
                    // TODO log it
                    AdtPlugin.log(e, "Failed to append to export.properties: %s", line);
                } finally {
                    mInternalTextUpdate = false;
                }
            }
        }
    }

    /**
     * Used when committing fields values to the model to retrieve the text
     * associated with a field.
     * <p/>
     * The base method only handles {@link Text} controls.
     *
     * CONTRACT: Derived classes CAN use this to support their own controls.
     *
     * @param field A control previously registered with {@link #getNameToField()}.
     * @return A non-null string to write to the properties files.
     */
    protected String getFieldText(Control field) {
        if (field instanceof Text) {
            return ((Text) field).getText();
        }
        return "";
    }

    /**
     * Called after all pages have been created, to let the parts initialize their
     * content based on the document's model.
     * <p/>
     * The model should be acceded via the {@link ExportEditor}.
     *
     * @param editor The {@link ExportEditor} instance.
     */
    public void onModelInit(ExportEditor editor) {

        // Start with a set of all the possible keywords and remove those we
        // found in the document as we read the lines.
        HashSet<String> allKeywords = new HashSet<String>(mNameToField.keySet());

        // Parse the lines in the document for patterns "keyword=value",
        // trimming all whitespace and discarding lines that start with # (comments)
        // then affect to the internal fields as appropriate.
        IDocument doc = editor.getDocument();
        int numLines = doc.getNumberOfLines();
        for (int i = 0; i < numLines; i++) {
            try {
                IRegion info = doc.getLineInformation(i);
                String line = doc.get(info.getOffset(), info.getLength());
                line = line.trim();
                if (line.startsWith("#")) {  //$NON-NLS-1$
                    continue;
                }

                int pos = line.indexOf('=');
                if (pos > 0 && pos < line.length() - 1) {
                    String key = line.substring(0, pos).trim();

                    Control field = mNameToField.get(key);
                    if (field != null) {
                        String value = line.substring(pos + 1).trim();
                        try {
                            mInternalTextUpdate = true;
                            setFieldText(field, value);
                            allKeywords.remove(key);
                        } finally {
                            mInternalTextUpdate = false;
                        }
                    }
                }

            } catch (BadLocationException e) {
                // TODO log it
                AdtPlugin.log(e, "Failed to set field to export.properties value");
            }
        }

        // Clear the text of any keyword we didn't find in the document
        Iterator<String> iterator = allKeywords.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            Control field = mNameToField.get(key);
            if (field != null) {
                try {
                    mInternalTextUpdate = true;
                    setFieldText(field, "");
                    iterator.remove();
                } finally {
                    mInternalTextUpdate = false;
                }
            }
        }
    }

    /**
     * Used when reading the model to set the field values.
     * <p/>
     * The base method only handles {@link Text} controls.
     *
     * CONTRACT: Derived classes CAN use this to support their own controls.
     *
     * @param field A control previously registered with {@link #getNameToField()}.
     * @param value A non-null string to that was read from the properties files.
     *              The value is an empty string if the property line is missing.
     */
    protected void setFieldText(Control field, String value) {
        if (field instanceof Text) {
            ((Text) field).setText(value);
        }
    }

    /**
     * Called after the document model has been changed. The model should be acceded via
     * the {@link ExportEditor} (e.g. getDocument, wrapRewriteSession)
     *
     * @param editor The {@link ExportEditor} instance.
     * @param event Specification of changes applied to document.
     */
    public void onModelChanged(ExportEditor editor, DocumentEvent event) {
        // To simplify and since we don't have many fields, just reload all the values.
        // A better way would to be to look at DocumentEvent which gives us the offset/length
        // and text that has changed.
        if (!mInternalTextUpdate) {
            onModelInit(editor);
        }
    }
}
