package org.apache.archiva.redback.role.validator;

/*
 * 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.
 */

import org.apache.archiva.components.graph.base.SimpleGraph;
import org.apache.archiva.components.graph.base.SimpleNode;
import org.apache.archiva.components.graph.util.Traversal;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.role.model.*;
import org.apache.archiva.redback.role.util.RoleModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * DefaultRoleModelValidator: validates completeness of the model
 *
 * @author: Jesse McConnell
 */
@Service("roleModelValidator")
public class DefaultRoleModelValidator
        implements RoleModelValidator {

    private static final Logger log = LoggerFactory.getLogger(DefaultRoleModelValidator.class);

    private List<String> validationErrors;

    public boolean validate(RedbackRoleModel model)
            throws RoleManagerException {
        validationErrors = null;

        validateRequiredStructure(model);
        validateResourceClosure(model);
        validateOperationClosure(model);
        validateChildRoleClosure(model);
        validateParentRoleClosure(model);
        validateTemplateClosure(model);
        validateNoRoleCycles(model);
        validateNoTemplateCycles(model);

        if (validationErrors == null) {
            return true;
        } else {
            return false;
        }
    }

    public List<String> getValidationErrors() {
        return validationErrors;
    }

    private void addValidationError(String error) {
        if (validationErrors == null) {
            validationErrors = new ArrayList<String>(0);
        }

        validationErrors.add(error);
    }

    /**
     * FIXME this should be taken care of by <required/> in modello, figure out why its not
     * in the meantime, implement the basics
     *
     * @param model
     */
    @SuppressWarnings("unchecked")
    private void validateRequiredStructure(RedbackRoleModel model) {
        // validate model has name

        for (ModelApplication application : model.getApplications()) {
            if (application.getId() == null) {
                addValidationError("model is missing application name");
            }

            // validate model has version
            if (application.getVersion() == null) {
                addValidationError(application.getId() + " is missing version");
            }

            // validate resource bits
            for (ModelResource resource : application.getResources()) {
                if (resource.getName() == null) {
                    addValidationError(resource.toString() + " missing name");
                }

                if (resource.getId() == null) {
                    addValidationError(resource.toString() + " missing id");
                }
            }

            // validate the operations
            for (ModelOperation operation : application.getOperations()) {
                if (operation.getName() == null) {
                    addValidationError(operation.toString() + " missing name");
                }

                if (operation.getId() == null) {
                    addValidationError(operation.toString() + " missing id");
                }
            }

            for (ModelRole role : application.getRoles()) {
                if (role.getId() == null) {
                    addValidationError(role.toString() + " missing id");
                }

                if (role.getName() == null) {
                    addValidationError(role.toString() + " missing name");
                }

                if (role.getPermissions() != null) {
                    for (ModelPermission permission : role.getPermissions()) {
                        if (permission.getName() == null) {
                            addValidationError(permission.toString() + " missing name");
                        }

                        if (permission.getId() == null) {
                            addValidationError(permission.toString() + " missing id");
                        }

                        if (permission.getOperation() == null) {
                            addValidationError(permission.toString() + " missing operations");
                        }

                        if (permission.getResource() == null) {
                            addValidationError(permission.toString() + " missing resource");
                        }
                    }
                }
            }

            for (ModelTemplate template : application.getTemplates()) {
                if (template.getId() == null) {
                    addValidationError(template.toString() + " missing id");
                }

                if (template.getNamePrefix() == null) {
                    addValidationError(template.toString() + " missing name prefix");
                }

                if (template.getPermissions() != null) {
                    for (ModelPermission permission : template.getPermissions()) {
                        if (permission.getName() == null) {
                            addValidationError(permission.toString() + " missing name");
                        }

                        if (permission.getId() == null) {
                            addValidationError(permission.toString() + " missing id");
                        }

                        if (permission.getOperation() == null) {
                            addValidationError(permission.toString() + " missing operations");
                        }

                        if (permission.getResource() == null) {
                            addValidationError(permission.toString() + " missing resource");
                        }
                    }
                }
            }
        }
    }

    /**
     * validate all operations in all declared permissions exist as declared in the operations section
     *
     * @param model
     */
    private void validateOperationClosure(RedbackRoleModel model) {
        List<String> operationIdList = RoleModelUtils.getOperationIdList(model);

        // check the operations in role permissions
        for (ModelApplication application : model.getApplications()) {
            for (ModelRole role : application.getRoles()) {
                if (role.getPermissions() != null) {
                    for (ModelPermission permission : role.getPermissions()) {
                        if (!operationIdList.contains(permission.getOperation())) {
                            addValidationError("missing operation: " + permission.getOperation() + " in permission "
                                    + permission.getId());
                        }
                    }
                }
            }

            // check the operations in template permissions
            for (ModelTemplate template : application.getTemplates()) {
                if (template.getPermissions() != null) {
                    for (ModelPermission permission : template.getPermissions()) {
                        if (!operationIdList.contains(permission.getOperation())) {
                            addValidationError("missing operation: " + permission.getOperation() + " in permission "
                                    + permission.getId());
                        }
                    }
                }
            }
        }
    }

    private void validateResourceClosure(RedbackRoleModel model) {
        List<String> resourceIdList = RoleModelUtils.getResourceIdList(model);
        for (ModelApplication application : model.getApplications()) {
            for (ModelRole role : application.getRoles()) {
                if (role.getPermissions() != null) {
                    for (ModelPermission permission : role.getPermissions()) {
                        if (!resourceIdList.contains(permission.getResource())) {
                            addValidationError("missing operation: " + permission.getResource() + " in permission "
                                    + permission.getId());
                        }
                    }
                }
            }
        }
    }

    private void validateChildRoleClosure(RedbackRoleModel model) {
        List<String> roleIdList = RoleModelUtils.getRoleIdList(model);
        for (ModelApplication application : model.getApplications()) {
            for (ModelRole role : application.getRoles()) {
                if (role.getChildRoles() != null) {
                    for (String childRoleId : role.getChildRoles()) {
                        if (!roleIdList.contains(childRoleId)) {
                            addValidationError(
                                    "missing role id: " + childRoleId + " in child roles of role " + role.getId());
                        }
                    }
                }
            }

            for (ModelTemplate template : application.getTemplates()) {
                if (template.getChildRoles() != null) {
                    for (String childRoleId : template.getChildRoles()) {
                        if (!roleIdList.contains(childRoleId)) {
                            addValidationError(
                                    "missing role id: " + childRoleId + " in child roles of template " + template.getId());
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void validateParentRoleClosure(RedbackRoleModel model) {
        List roleIdList = RoleModelUtils.getRoleIdList(model);

        for (ModelApplication application : model.getApplications()) {
            for (ModelRole role : application.getRoles()) {
                if (role.getParentRoles() != null) {
                    for (String parentRoleId : role.getParentRoles()) {
                        if (!roleIdList.contains(parentRoleId)) {
                            addValidationError(
                                    "missing role id: " + parentRoleId + " in parent roles of role " + role.getId());
                        }
                    }
                }
            }

            for (ModelTemplate template : application.getTemplates()) {
                if (template.getParentRoles() != null) {
                    for (String parentRoleId : template.getParentRoles()) {
                        if (!roleIdList.contains(parentRoleId)) {
                            addValidationError("missing role id: " + parentRoleId + " in parent roles of template "
                                    + template.getId());
                        }
                    }
                }
            }
        }
    }

    private void validateTemplateClosure(RedbackRoleModel model) {
        List templateIdList = RoleModelUtils.getTemplateIdList(model);

        // template name prefix must be unique
        List<String> templateNamePrefixList = new ArrayList<String>();

        for (ModelApplication application : model.getApplications()) {
            for (ModelTemplate template : application.getTemplates()) {
                if (template.getParentTemplates() != null) {
                    for (String parentTemplateId : template.getParentTemplates()) {
                        if (!templateIdList.contains(parentTemplateId)) {
                            addValidationError(
                                    "missing template id: " + parentTemplateId + " in parent templates of template "
                                            + template.getId());
                        }
                    }
                }

                if (template.getChildTemplates() != null) {
                    for (String childTemplateId : template.getChildTemplates()) {
                        if (!templateIdList.contains(childTemplateId)) {
                            addValidationError(
                                    "missing template id: " + childTemplateId + " in child templates of template "
                                            + template.getId());
                        }
                    }
                }

                if (!templateNamePrefixList.contains(template.getNamePrefix())) {
                    templateNamePrefixList.add(template.getNamePrefix());
                } else {
                    addValidationError("duplicate name prefix detected: " + template.getNamePrefix());
                }
            }
        }
    }

    /**
     * We are not allowed to have cycles between roles, this method is to detect and raise a red flag when that happens.
     *
     * @param model
     */
    private void validateNoRoleCycles(RedbackRoleModel model) {
        log.debug("Validating cycles in role model");
        SimpleGraph graph = RoleModelUtils.generateRoleGraph(model);
        SimpleNode rootNode = graph.getNode(RoleModelUtils.ROOT);
        SimpleNode n;
        if ((n = Traversal.findFirstCycleNode(rootNode))!=null) {
            log.debug("Adding template cycle validation error for node {}", n.getId());
            addValidationError("Cycle detected at "+n.getId());
        }
    }

    /**
     * We are not allowed to have cycles between template either, this method is to detect and
     * raise a red flag when that happens.  Templates are a bit more complex since they have both
     * child and parent roles, as well as runtime parent and child templates
     * <p>
     * the id should be sufficient to test cycles here even though in runtime the id's do not need to be
     * unique since it is the binding of a namePrefix and a resource that makes them unique
     *
     * @param model
     */
    private void validateNoTemplateCycles(RedbackRoleModel model) {
        log.debug("Validating cycles in role template model ");
        SimpleGraph graph = RoleModelUtils.generateTemplateGraph(model);
        SimpleNode rootNode = graph.getNode(RoleModelUtils.ROOT);
        SimpleNode n;
        if ((n = Traversal.findFirstCycleNode(rootNode)) != null) {
            log.debug("Adding template cycle validation error for node {}", n.getId());
            addValidationError("Template cycle detected at "+n.getId());
        }
    }
}
