/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.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.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.faces.facelets.component.expandabletable;

import javax.faces.event.ActionEvent;
import java.io.Serializable;
import java.util.ArrayList;


/**
 * The <code>ExpandableRecord</code> class is the primary class for use with the
 * <code>expandableTable</code> custom component.  The class contains the necessary
 * methods and attributes needed for the <code>expandableTable</code> custom component
 * to function.  This classes uses <code>Generics<code> to link to a user defined data
 * object.
 */
public class ExpandableRecord implements ExpandableRecordInterface, Serializable {

    // Style for column that holds expand/contract image toggle, in the sales
    // record row.
    protected String indentStyleClass = "";
    // Style for all other columns in the sales record row.
    protected String rowStyleClass = "";
    // callback to list which contains all data in the dataTable.  This 
    // callback is needed so that a node can be set in the expanded state
    // at construction time.
    protected ArrayList parentList;
    //Indicates if node is in expanded state.
    protected boolean isExpanded;
    //List of child records
    protected ArrayList childRecords =
            new ArrayList();
    //Generic object that represents the user generated data object.
    private Object record;
    //STores the type of node, parent or child.
    protected String nodeType;


    /**
     * Creates a new <code>ExpandableRecord</code>.  This constructor should be used when
     * creating <code>ExpandableRecord</code> objects which will contain children.
     *
     * @param indentStyleClass style class for the expand/contract image column
     * @param rowStyleClass    style class for the data columns
     * @param parentList       list of parent items
     * @param isExpanded       true, indicates that the specified node will be
     *                         expanded by default, otherwise, false
     * @param record           user created object that is linked to this parent
     *                         object
     * @param nodeType         can be either parent or child
     */
    public ExpandableRecord(String indentStyleClass,
                            String rowStyleClass,
                            ArrayList parentList,
                            boolean isExpanded,
                            Object record,
                            String nodeType) {
        this.indentStyleClass = indentStyleClass;
        this.rowStyleClass = rowStyleClass;
        this.parentList = parentList;
        this.parentList.add(this);
        this.isExpanded = isExpanded;
        if (this.isExpanded) {
            expandNodeAction();
        }
        this.record = record;
        this.nodeType = nodeType;
    }

    /**
     * Creates a new <code>ExpandableRecord</code> object.  This constructor
     * should be used when creating an <code>ExpandableRecord</code> object that
     * will be a child of some other <code>ExpanableRecord</code> object.  This
     * created <code>ExpandableRecord</code> has no image states defined.
     *
     * @param indentStyleClass style class for the expand/contract image column
     * @param rowStyleClass    style class for the data columns
     * @param record           user created object that is linked to this parent
     *                         object
     * @param nodeType         can be either parent or child
     */
    public ExpandableRecord(String indentStyleClass, String rowStyleClass,
                            Object record, String nodeType) {
        this.indentStyleClass = indentStyleClass;
        this.rowStyleClass = rowStyleClass;
        this.record = record;
        this.nodeType = nodeType;
    }

    /**
     * Gets the renderable state of the contract/expand image toggle.
     *
     * @return true if images shoulc be drawn; otherwise, false.
     */
    public boolean isRenderImage() {
        return childRecords != null && childRecords.size() > 0;
    }

    /**
     * Toggles the expanded state of this record.
     *
     * @param event jsf action event.
     */
    public void toggleSubGroupAction(ActionEvent event) {
        isExpanded = !isExpanded;
        if (isExpanded) {
            expandNodeAction();
        } else {
            contractNodeAction();
        }
    }

    /**
     * Adds a child sales record to this sales group.
     *
     * @param expandableRecord child record to add to this record.
     */
    public void addChildRecord(ExpandableRecord expandableRecord) {
        if (childRecords != null && expandableRecord != null) {
            childRecords.add(expandableRecord);
            if (isExpanded) {
                contractNodeAction();
                expandNodeAction();
            }
        }

    }

    /**
     * Removes the specified child record from this group.
     *
     * @param expandableRecord child record to remove.
     */
    public void removeChildRecord(ExpandableRecord expandableRecord) {
        if (childRecords != null && expandableRecord != null) {
            if (isExpanded) {
                contractNodeAction();
            }
            childRecords.remove(expandableRecord);
            if (isExpanded) {
                contractNodeAction();
                expandNodeAction();
            }
        }
    }

    /**
     * Utility metod to add all child nodes to the parent <code>dataTable</code>
     * list.
     */
    public void expandNodeAction() {
        if (childRecords != null && childRecords.size() > 0) {
            int index = parentList.indexOf(this);
            parentList.addAll(index + 1, childRecords);
        }
    }

    /**
     * Utility method to remove all the child nodes from the parent
     * <code>dataTable</code> list.
     */
    public void contractNodeAction() {
        if (childRecords != null && childRecords.size() > 0) {
            parentList.removeAll(childRecords);
        }
    }

    /**
     * Gets the style class name used to define the first column of a
     * record row.  This first column is where an expand/contract
     * image is placed.
     *
     * @return indentStyleClass style class for the expand/contract image column
     */
    public String getIndentStyleClass() {
        return indentStyleClass;
    }

    /**
     * Gets the style class name used to define all other columns in the
     * record row, except the first column.
     *
     * @return rowStyleClass style class for the data columns
     */
    public String getRowStyleClass() {
        return rowStyleClass;
    }


    /**
     * Gets the list of child records.
     *
     * @return childRecords list of child records
     */
    public ArrayList getChildRecords() {
        return childRecords;
    }

    /**
     * Gets the user defined data record object.
     *
     * @return record user defined data record.
     */
    public Object getRecord() {
        return record;
    }

    /**
     * Gets the state of the parent <code>ExpandableRecord</code> object.
     *
     * @return isExpanded true, indicates that the specified node will be
     *         expanded by default, otherwise, false
     */
    public boolean getIsExpanded() {
        return isExpanded;
    }

    /**
     * Gets the node type value of the <code>ExpandableRecord</code> object.
     *
     * @return nodeType can be either parent or child
     */
    public String getNodeType() {
        return nodeType;
    }
}
