package org.vaadin.viritinv7.fields;

import org.vaadin.viritin.button.MButton;
import org.vaadin.viritin.layouts.MHorizontalLayout;

import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.Page;
import com.vaadin.server.Resource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Layout;
import com.vaadin.ui.themes.ValoTheme;
import com.vaadin.v7.data.Property;
import com.vaadin.v7.data.util.converter.Converter;
import com.vaadin.v7.event.FieldEvents;
import com.vaadin.v7.ui.AbstractTextField;
import com.vaadin.v7.ui.CustomField;

/**
 * A textfield with an attached button, that clears the textfield. Most methods
 * in this class delegate to the textfield, some to the button.
 * ClearableTextField should work as a drop-in replacement for TextFiled /
 * MTextField.
 *
 * @author Niki
 */
public class ClearableTextField extends CustomField {

    private final MTextField textfield = new MTextField();
    private final MButton clearButton = new MButton(VaadinIcons.CLOSE)
            .withStyleName(ValoTheme.BUTTON_ICON_ONLY);
    private final MHorizontalLayout root = new MHorizontalLayout()
            .expand(textfield).add(clearButton)
            .withSpacing(false)
            .withFullWidth()
            .withStyleName("clearable-textfield");

    @SuppressWarnings("OverridableMethodCallInConstructor")
    public ClearableTextField() {
        clearButton.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                textfield.clear();
                textfield.focus();
            }
        });

        textfield.addValueChangeListener(new ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent event) {
                setValue(textfield.getValue());
            }
        });

        textfield.addTextChangeListener(new FieldEvents.TextChangeListener() {
            @Override
            public void textChange(FieldEvents.TextChangeEvent event) {
                setValue(event.getText());
            }
        });

        setWidth("300px");
    }

    @SuppressWarnings("OverridableMethodCallInConstructor")
    public ClearableTextField(String caption) {
        this();
        this.setCaption(caption);
    }

    public ClearableTextField(Property dataSource) {
        this();
        textfield.setPropertyDataSource(dataSource);

    }

    @SuppressWarnings("OverridableMethodCallInConstructor")
    public ClearableTextField(String caption, Property dataSource) {
        this();
        this.setCaption(caption);
        textfield.setPropertyDataSource(dataSource);

    }

    @SuppressWarnings("OverridableMethodCallInConstructor")
    public ClearableTextField(String caption, String value) {
        this();
        this.setCaption(caption);
        textfield.setValue(value);
    }

    /**
     *
     * @return The TextField from the composition
     */
    public MTextField getTextfield() {
        return textfield;
    }

    /**
     *
     * @return The root CssLayout
     */
    public Layout getRoot() {
        return root;
    }

    /**
     *
     * @return The Button
     */
    public MButton getClearButton() {
        return clearButton;
    }

    @Override
    public void setReadOnly(boolean readOnly) {
        super.setReadOnly(readOnly);
        textfield.setReadOnly(readOnly);
        clearButton.setEnabled(!readOnly);
    }

    @Override
    public void setImmediate(boolean immediate) {
        super.setImmediate(immediate);
        textfield.setImmediate(immediate);
    }

    /**
     * A method to add custom click listener to the clear button.
     *
     * @see Button#addClickListener(Button.ClickListener listener)
     * @param listener the listener to be added to the clear button
     */
    public void addClickListener(Button.ClickListener listener) {
        clearButton.addClickListener(listener);
    }

    public void removeClickListener(Button.ClickListener listener) {
        clearButton.removeClickListener(listener);
    }

    public void click() {
        clearButton.click();
    }

    public void setClickShortcut(int keyCode, int... modifiers) {
        clearButton.setClickShortcut(keyCode, modifiers);
    }

    public void removeClickShortcut() {
        clearButton.removeClickShortcut();
    }

    public void setIcon(Resource icon, String iconAltText) {
        clearButton.setIcon(icon, iconAltText);
    }

    public String getIconAlternateText() {
        return clearButton.getIconAlternateText();
    }

    public void setIconAlternateText(String iconAltText) {
        clearButton.setIconAlternateText(iconAltText);
    }

    public void setHtmlContentAllowed(boolean htmlContentAllowed) {
        clearButton.setHtmlContentAllowed(htmlContentAllowed);
    }

    public boolean isHtmlContentAllowed() {
        return clearButton.isHtmlContentAllowed();
    }

    @Override
    public void clear() {
        super.clear();
        textfield.clear();
    }

    public String getNullRepresentation() {
        return textfield.getNullRepresentation();
    }

    public boolean isNullSettingAllowed() {
        return textfield.isNullSettingAllowed();
    }

    public void setNullRepresentation(String nullRepresentation) {
        textfield.setNullRepresentation(nullRepresentation);
    }

    public void setNullSettingAllowed(boolean nullSettingAllowed) {
        textfield.setNullSettingAllowed(nullSettingAllowed);
    }

    @Override
    public boolean isEmpty() {
        return super.isEmpty();
    }

    public int getMaxLength() {
        return textfield.getMaxLength();
    }

    public void setMaxLength(int maxLength) {
        textfield.setMaxLength(maxLength);
    }

    public int getColumns() {
        return textfield.getColumns();
    }

    public void setColumns(int columns) {
        textfield.setColumns(columns);
    }

    public String getInputPrompt() {
        return textfield.getInputPrompt();
    }

    public void setInputPrompt(String inputPrompt) {
        textfield.setInputPrompt(inputPrompt);
    }

    public void setTextChangeEventMode(AbstractTextField.TextChangeEventMode inputEventMode) {
        textfield.setTextChangeEventMode(inputEventMode);
    }

    public AbstractTextField.TextChangeEventMode getTextChangeEventMode() {
        return textfield.getTextChangeEventMode();
    }

    public void addTextChangeListener(FieldEvents.TextChangeListener listener) {
        textfield.addTextChangeListener(listener);
    }

    public void removeTextChangeListener(FieldEvents.TextChangeListener listener) {
        textfield.removeTextChangeListener(listener);
    }

    public void setTextChangeTimeout(int timeout) {
        textfield.setTextChangeTimeout(timeout);
    }

    public int getTextChangeTimeout() {
        return textfield.getTextChangeTimeout();
    }

    public void selectAll() {
        textfield.selectAll();
    }

    public void setSelectionRange(int pos, int length) {
        textfield.setSelectionRange(pos, length);
    }

    public void setCursorPosition(int pos) {
        textfield.setCursorPosition(pos);
    }

    public int getCursorPosition() {
        return textfield.getCursorPosition();
    }

    public void addFocusListener(FocusListener listener) {
        textfield.addFocusListener(listener);
    }

    public void removeFocusListener(FocusListener listener) {
        textfield.removeFocusListener(listener);
    }

    public void addBlurListener(BlurListener listener) {
        textfield.addBlurListener(listener);
    }

    public void removeBlurListener(BlurListener listener) {
        textfield.removeBlurListener(listener);
    }

    public ClearableTextField withCaption(String caption) {
        super.setCaption(caption);
        return this;
    }

    public ClearableTextField withConversionError(String message) {
        setConversionError(message);
        return this;
    }

    public ClearableTextField withConverter(Converter<String, ?> converter) {
        setConverter(converter);
        return this;
    }

    public ClearableTextField withFullWidth() {
        this.setWidth("100%");
        return this;
    }

    public ClearableTextField withValue(String value) {
        setValue(value);
        return this;
    }

    protected void doEagerValidation() {
        textfield.doEagerValidation();
    }

    @Override
    protected void setInternalValue(Object newValue) {
        super.setInternalValue(newValue);
        textfield.setValue(newValue.toString());
    }

    @Override
    public ErrorMessage getErrorMessage() {
        final ErrorMessage errorMessage = super.getErrorMessage();
        if (errorMessage == null) {
            textfield.removeStyleName("error");
        } else {
            textfield.addStyleName("error");
        }
        return errorMessage;
    }

    @Override
    public void setComponentError(ErrorMessage componentError) {
        super.setComponentError(componentError);
        if (componentError == null) {
            textfield.removeStyleName("error");
        } else {
            textfield.addStyleName("error");
        }
    }

    @Override
    public void beforeClientResponse(boolean initial) {
        super.beforeClientResponse(initial); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void focus() {
        textfield.focus();
    }

    @Override
    protected Component initContent() {
        return root;
    }

    @Override
    public Class getType() {
        return String.class;
    }

    @Override
    public void attach() {
        super.attach();
        Page.getCurrent().getStyles().add(
                ".clearable-textfield .v-widget {\n"
                + "	border-radius: 4px 4px 4px 4px;\n"
                + "}\n"
                + ".clearable-textfield .v-slot:last-child>.v-widget {\n"
                + "	border-top-left-radius: 0;\n"
                + "	border-bottom-left-radius: 0; margin-left:-1px\n"
                + "}\n"
                + "\n"
                + ".clearable-textfield .v-slot:first-child>.v-widget {\n"
                + "	border-top-right-radius: 0;\n"
                + "	border-bottom-right-radius: 0;\n"
                + "}\n");
    }

}