/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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.queplix.core.client.app.vo;

import com.queplix.core.client.app.vo.uisettings.DialogUISettings;

/**
 * Base class for field metadata. This implements logic by storing field type
 * and field id.
 *
 * @author Sergey Kozmin
 * @since 13 Oct 2006
 */
public class BaseFieldMeta implements FieldMeta {
    // ----- GWT RPC serialization perfomance improvement
    private static final int REQUIRED_FLAG = 1;
    private static final int DESCRIPTIVE_FLAG = 2;
    private static final int READONLY_FLAG = 4;
    private static final int SEARCHABLE_FLAG = 8;
    private static final int HAS_DEF_SRC_ATTR_FLAG = 16;
    private static final int INLINE_FLAG = 32;
    private static final int CLEAR_FLAG = 64;

    // operate on bits rather than having a bunch of booleans:
    private int flags;
    // ----- End of GWT RPC serialization perfomance improvement

    private String fieldID;
    private int fieldType;
    private String caption;
    private FamgMeta.Index linkedForm;
    private DialogUISettings uiSettings;

    public BaseFieldMeta(int fieldType, String fieldID, String caption,
                         boolean required, boolean descriptive,
                         boolean readOnly, boolean searchable,
                         boolean hasDefSrcAttribute) {
        this.fieldID = fieldID;
        this.fieldType = fieldType;
        setRequired(required);
        this.caption = caption;
        setDescriptive(descriptive);
        setReadOnly(readOnly);
        setSearchable(searchable);
        setHasDefSrcAttribute(hasDefSrcAttribute);
    }

    public BaseFieldMeta(int fieldType, String fieldID, String caption,
                         boolean required, boolean descriptive) {
        this(fieldType, fieldID, caption, required, descriptive, false,
                true, false);
    }

    public BaseFieldMeta(int fieldType, String fieldID, String caption,
                         boolean required) {
        this(fieldType, fieldID, caption, required, false);
    }

    public BaseFieldMeta(int fieldType, String fieldID, String caption) {
        this(fieldType, fieldID, caption, false);
    }

    public BaseFieldMeta(int fieldType, String fieldID) {
        this(fieldType, fieldID, "", false);
    }

    public BaseFieldMeta() {
        this(-1, "", "", false);
    }

    public boolean isReadOnly() {
        return isFlag(READONLY_FLAG);
    }

    public void setReadOnly(boolean readonly) {
        setFlag(READONLY_FLAG, readonly);
    }

    public boolean isSearchable() {
        return isFlag(SEARCHABLE_FLAG);
    }

    public void setSearchable(boolean searchable) {
        setFlag(SEARCHABLE_FLAG, searchable);
    }

    public boolean isRequired() {
        return isFlag(REQUIRED_FLAG);
    }

    public void setRequired(boolean required) {
        setFlag(REQUIRED_FLAG, required);
    }

    public int getDataType() {
        return fieldType;
    }

    public String getFieldID() {
        return fieldID;
    }

    public void setFieldID(String fieldID) {
        this.fieldID = fieldID;
    }

    public void setFieldType(int fieldType) {
        this.fieldType = fieldType;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
    }

    public boolean isDescriptive() {
        return isFlag(DESCRIPTIVE_FLAG);
    }

    public void setDescriptive(boolean descriptive) {
        setFlag(DESCRIPTIVE_FLAG, descriptive);
    }

    public boolean hasDefSrcAttribute() {
        return isFlag(HAS_DEF_SRC_ATTR_FLAG);
    }

    public void setHasDefSrcAttribute(boolean hasDefSrcAttribute) {
        setFlag(HAS_DEF_SRC_ATTR_FLAG, hasDefSrcAttribute);
    }

    public FamgMeta.Index getLinkedForm() {
        return linkedForm;
    }

    public void setLinkedForm(FamgMeta.Index linkedForm) {
        this.linkedForm = linkedForm;
    }

    public boolean isForGrid() {
        switch(fieldType) {
            case CHECKBOX:
            case DATEFIELD:
            case LISTBOX:
            case TEXTAREA:
            case TEXTBOX:
            case ENTITYREFERENCE:
                return true;
        }
        return false;
    }

    public DialogUISettings getUISettings() {
        return uiSettings;
    }

    public void setUISettings(DialogUISettings uiSettings) {
        this.uiSettings = uiSettings;
    }

    public FieldMeta cloneElementMeta() {
        return new BaseFieldMeta(fieldType, fieldID, caption, isRequired(),
                isDescriptive(), isReadOnly(), isSearchable(),
                hasDefSrcAttribute());
    }

    /**
     * Compares items.
     *
     * @param items        first item
     * @param anotherItems second item.
     * @return is items equals. If at least one of object is null it returns false, otherwise compares by items.
     */
    public static boolean isItemsEquals(SubsetItemMeta[] items,
                                        SubsetItemMeta[] anotherItems) {
        boolean ret = false;
        if(items == null || anotherItems == null) {
            ret = false;
        } else {
            if(items.length == anotherItems.length) {
                ret = true;
                for(int i = 0; i < anotherItems.length; i++) {
                    if(!(anotherItems[i].getId() == items[i].getId()
                            && anotherItems[i].getCaption().equalsIgnoreCase(
                            items[i].getCaption()))) {
                        ret = false;
                        break;
                    }
                }
            }
        }
        return ret;
    }

    public boolean isInline() {
        return isFlag(INLINE_FLAG);
    }

    public void setInline(boolean inline) {
        setFlag(INLINE_FLAG, inline);
    }

    public boolean hasClearAttribute() {
        return isFlag(CLEAR_FLAG);
    }

    public void setClearAttribute(boolean clear) {
        setFlag(CLEAR_FLAG, clear);
    }

    private boolean isFlag(int flag) {
        return (flags & flag) != 0;
    }

    private void setFlag(int flag, boolean value) {
        if(value) {
            flags |= flag;
        } else {
            flags &= ~flag;
        }
    }
}
