/*
 * Copyright (C) 2014 University of Dundee & Open Microscopy Environment.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.openmicroscopy.shoola.env.data.util;

import pojos.DataObject;

/**
 * Encapsulates a single object found by a search together with the search scope
 * (name, description, etc.) it was found with.
 * 
 * Multiple search results are supposed to be held in an
 * {@link AdvancedSearchResultCollection}
 * 
 * @author Dominik Lindner &nbsp;&nbsp;&nbsp;&nbsp; <a
 *         href="mailto:d.lindner@dundee.ac.uk">d.lindner@dundee.ac.uk</a>
 * 
 * @since 5.0
 */
public class AdvancedSearchResult {

    /** The scope (name, description, ...), see {@link SearchDataContext} */
    private int scopeId;

    /** Indicates the type (ImageData, DatasetData, ...) see {@link DataObject} */
    private Class<? extends DataObject> type;

    /** Id of the found object */
    private long objectId = -1;

    /** Id of the group the object belongs to */
    private long groupId = -1;

    /** The found object itself */
    private DataObject object;
    
    /** Indicates that this result is an ID match */
    private boolean idMatch = false;

    /**
     * Create a new instance
     */
    public AdvancedSearchResult() {
    }

    /**
     * Create a new instance
     * 
     * @param scopeId
     *            Id of the search scope, see {@link SearchDataContext}
     * @param type
     *            Type of the object to search
     * @param objectId
     *            Id of the found object
     */
    public AdvancedSearchResult(int scopeId, Class<? extends DataObject> type,
            long objectId, long groupId) {
        this.scopeId = scopeId;
        this.type = type;
        this.objectId = objectId;
        this.groupId = groupId;
    }

    /**
     * The Id of the search scope, e. g. name, description, ... see
     * {@link SearchDataContext}
     * 
     * @return
     */
    public int getScopeId() {
        return scopeId;
    }

    /**
     * Set the id of the search scope, e. g. name, description, ... see
     * {@link SearchDataContext}
     * 
     * @param scopeId
     */
    public void setScopeId(int scopeId) {
        this.scopeId = scopeId;
    }

    /**
     * Get the type (class) of objects to search for see {@link DataObject}
     * 
     * @return
     */
    public Class<? extends DataObject> getType() {
        return type;
    }

    /**
     * Set the type (class) of objects to search for see {@link DataObject}
     * 
     * @param type
     */
    public void setType(Class<? extends DataObject> type) {
        this.type = type;
    }

    /**
     * Set the Id of the found object
     * 
     * @return
     */
    public long getObjectId() {
        return objectId;
    }

    /**
     * Get the Id of the found object
     * 
     * @param objectId
     */
    public void setObjectId(long objectId) {
        this.objectId = objectId;
    }

    /**
     * Get the found object
     * 
     * @return
     */
    public DataObject getObject() {
        return object;
    }

    /**
     * Get the group id of the object
     * 
     * @return
     */
    public long getGroupId() {
        return groupId;
    }

    /**
     * Set the group id of the object
     * 
     * @param groupId
     */
    public void setGroupId(long groupId) {
        this.groupId = groupId;
    }

    /** 
     * Indicates if this result is an ID match 
     */
    public boolean isIdMatch() {
        return idMatch;
    }

    /**
     * Set to <code>true</code> if this result is an ID match
     * @param idMatch
     */
    public void setIdMatch(boolean idMatch) {
        this.idMatch = idMatch;
    }

    /**
     * Set the found object
     * 
     * @param object
     */
    public void setObject(DataObject object) {
        if (objectId >= 0) {
            if (object.getId() != objectId)
                throw new IllegalArgumentException(
                        "objectId does not match the object!");
        } else {
            objectId = object.getId();
        }

        if (type != null) {
            if (!object.getClass().equals(type))
                throw new IllegalArgumentException("Cannot add a "
                        + object.getClass().getSimpleName()
                        + " to an AdvancedSearchResult intended for "
                        + type.getSimpleName() + "!");
        } else {
            type = object.getClass();
        }

        if (groupId >= 0) {
            if (object.getGroupId() != groupId)
                throw new IllegalArgumentException("The object's groupId ("
                        + object.getGroupId()
                        + ") does not match the previous set groupId ("
                        + groupId + ") !");
        } else {
            groupId = object.getGroupId();
        }

        this.object = object;
    }

    @Override
    public String toString() {
        return "AdvancedSearchResult [scopeId=" + scopeId + ", type="
                + (type != null ? type.getSimpleName() : "null")
                + ", objectId=" + objectId + ", groupId=" + groupId + "]";
    }

}
