/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 *  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 org.apache.bval;


import org.apache.bval.model.ValidationContext;
import org.apache.bval.model.ValidationListener;

import java.io.Serializable;
import java.util.*;

/**
 * Description: Implements a contains to hold and transport validation results<br/>
 */
public class ValidationResults implements ValidationListener, Serializable {
    private static final long serialVersionUID = 1L;

    private Map<String, List<Error>> errorsByReason;
    private Map<Object, Map<String, List<Error>>> errorsByOwner;


    /**
     * API to add an error to the validation results.
     *
     * @param reason       - Features from {@link org.apache.bval.model.Features.Property}
     *                       or custom reason of validation error
     * @param context        - context information (bean, propertyName, value, ...)
     */
    public <T extends ValidationListener> void addError(String reason, ValidationContext<T> context) {
        Error error = createError(reason, context.getBean(), context.getPropertyName());
        addError(error, context);
    }


     /**
     * API to add an error to the validation results.
     *
     * @param error       - holding the description of reason and object to describe
      *                     the validation error
     * @param context     - null or the context to provide additional information
     */
    public <T extends ValidationListener> void addError(Error error, ValidationContext<T> context) {
        if (errorsByReason == null) {
            initialize();
        }
        addToReasonBucket(error);
        addToOwnerBucket(error);
    }

    /**
     * Old API to add an error to the validation results when no context is available.
     *
     * @param reason       - Features from {@link org.apache.bval.model.Features.Property} or custom validation reason
     * @param bean         - (optional) owner bean or null
     * @param propertyName - (optional) propertyName where valiation error occurred or null
     */
    public void addError(String reason, Object bean, String propertyName) {
        addError(createError(reason, bean, propertyName), null);
    }

    /**
     * Create an Error object.
     * @param reason
     * @param owner
     * @param propertyName
     * @return new {@link Error}
     */
    protected Error createError(String reason, Object owner, String propertyName) {
        return new Error(reason, owner, propertyName);
    }

    /**
     * initialize the error-buckets now when needed and
     * not on instance creation to save memory garbage.
     */
    protected void initialize() {
        errorsByReason = new LinkedHashMap<String, List<Error>>();
        errorsByOwner = new LinkedHashMap<Object, Map<String, List<Error>>>();
    }

    /**
     * Add an Error to the set of Errors shared by a particular "reason."
     * @param error
     * @see {@link Error#getReason()}
     */
    protected void addToReasonBucket(Error error) {
        if (error.getReason() == null) return;

        List<Error> errors = errorsByReason.get(error.getReason());
        if (errors == null) {
            errors = new ArrayList<Error>();
            errorsByReason.put(error.getReason(), errors);
        }
        errors.add(error);
    }

    /**
     * Add an Error to the property-keyed map of Errors maintained for this Error's owner.
     * @param error
     * @see {@link Error#getOwner()}
     */
    protected void addToOwnerBucket(Error error) {
        if (error.getOwner() == null) return;

        Map<String, List<Error>> errors = errorsByOwner.get(error.getOwner());
        if (errors == null) {
            errors = new HashMap<String, List<Error>>();
            errorsByOwner.put(error.getOwner(), errors);
        }
        List<Error> list = errors.get(error.getPropertyName());
        if (list == null) {
            list = new ArrayList<Error>();
            errors.put(error.getPropertyName(), list);
        }
        list.add(error);
    }

    /**
     * Get the map of Errors by reason; 
     * key = reason, value = list of errors for this reason
     * @return map
     */
    public Map<String, List<Error>> getErrorsByReason() {
        if (errorsByReason == null) return Collections.emptyMap();
        return errorsByReason;
    }

    /**
     * Get the map of Errors by owner;
     * key = owner, value = map with:<br>
     * &nbsp;&nbsp; key = propertyName, value = list of errors for this owner.propertyName
     * @return map
     */
    public Map<Object, Map<String, List<Error>>> getErrorsByOwner() {
        if (errorsByOwner == null) return Collections.emptyMap();
        return errorsByOwner;
    }

    /**
     * Learn whether these results are empty/error-free.
     * @return true when there are NO errors in this validation result
     */
    public boolean isEmpty() {
        if (errorsByReason == null ||
              (errorsByReason.isEmpty() && errorsByOwner.isEmpty())) return true;
        for (List<Error> list : errorsByReason.values()) {
            if (!list.isEmpty()) return false;
        }
        for (Map<String, List<Error>> map : errorsByOwner.values()) {
            for (List<Error> list : map.values()) {
                if (!list.isEmpty()) return false;
            }
        }
        return true;
    }

    /**
     * Learn whether there is an Error keyed to a specified reason description.
     * @param reason
     * @return boolean
     * @see {@link Error#getReason()}
     */
    public boolean hasErrorForReason(String reason) {
        if (errorsByReason == null) return false;
        List<Error> errors = errorsByReason.get(reason);
        return errors != null && !errors.isEmpty();
    }

    /**
     * Learn whether <code>bean</code> has any errors keyed to property <code>propertyName</code>.
     * @param bean
     * @param propertyName - may be null: any property is checked
     *                     OR the name of the property to check
     * @return boolean
     */
    public boolean hasError(Object bean, String propertyName) {
        if (errorsByOwner == null) return false;
        Map<String, List<Error>> errors = errorsByOwner.get(bean);
        if (errors == null) return false;
        if (propertyName != null) {
            List<Error> list = errors.get(propertyName);
            return list != null && !list.isEmpty();
        } else {
            for (List<Error> list : errors.values()) {
                if (!list.isEmpty()) return true;
            }
            return false;
        }
    }

    /**
     * {@inheritDoc}
     */
    public String toString() {
        return "ValidationResults{" + errorsByOwner + "}";
    }
}
