/*
 * 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.tinkerpop.gremlin.groovy.jsr223.dsl.credential;

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.mindrot.jbcrypt.BCrypt;

import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.drop;

/**
 * A DSL for managing a "credentials graph" used by Gremlin Server for simple authentication functions.  If the
 * {@link Graph} is transactional, new transactions will be started for each method call.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 * @deprecated As of release 3.3.3, replaced by {@link  CredentialTraversalDsl}.
 */
@Deprecated
public class CredentialGraph {

    private final int BCRYPT_ROUNDS = 4;
    private final Graph graph;
    private final GraphTraversalSource g;
    private final boolean supportsTransactions;

    public CredentialGraph(final Graph graph) {
        this.graph = graph;
        g = graph.traversal();
        supportsTransactions = graph.features().graph().supportsTransactions();
    }

    /**
     * Finds a user by username and return {@code null} if one could not be found.
     *
     * @throws IllegalStateException if there is more than one user with a particular username.
     */
    public Vertex findUser(final String username) {
        if (supportsTransactions) g.tx().rollback();
        final GraphTraversal<Vertex,Vertex> t = g.V().has(CredentialGraphTokens.PROPERTY_USERNAME, username);
        final Vertex v = t.hasNext() ? t.next() : null;
        if (t.hasNext()) throw new IllegalStateException(String.format("Multiple users with username %s", username));
        return v;
    }

    /**
     * Creates a new user.
     *
     * @return the newly created user vertex
     */
    public Vertex createUser(final String username, final String password) {
        if (findUser(username) != null) throw new IllegalStateException("User with this name already exists");
        if (supportsTransactions) graph.tx().rollback();

        try {
            final Vertex v =  graph.addVertex(T.label, CredentialGraphTokens.VERTEX_LABEL_USER,
                                              CredentialGraphTokens.PROPERTY_USERNAME, username,
                                              CredentialGraphTokens.PROPERTY_PASSWORD, BCrypt.hashpw(password, BCrypt.gensalt(BCRYPT_ROUNDS)));
            if (supportsTransactions) graph.tx().commit();
            return v;
        } catch (Exception ex) {
            if (supportsTransactions) graph.tx().rollback();
            throw new RuntimeException(ex);
        }
    }

    /**
     * Removes a user by name.
     *
     * @return the number of users removed (which should be one or zero)
     */
    public long removeUser(final String username) {
        if (supportsTransactions) graph.tx().rollback();
        try {
            final long count = g.V().has(CredentialGraphTokens.PROPERTY_USERNAME, username).sideEffect(drop()).count().next();
            if (supportsTransactions) graph.tx().commit();
            return count;
        } catch (Exception ex) {
            if (supportsTransactions) graph.tx().rollback();
            throw new RuntimeException(ex);
        }
    }

    /**
     * Get a count of the number of users in the database.
     */
    public long countUsers() {
        if (supportsTransactions) graph.tx().rollback();
        return g.V().hasLabel(CredentialGraphTokens.VERTEX_LABEL_USER).count().next();
    }

    @Override
    public String toString() {
        return "CredentialGraph{" +
                "graph=" + graph +
                '}';
    }

    /**
     * Wrap up any {@link Graph} instance in the {@code CredentialGraph} DSL.
     */
    public static CredentialGraph credentials(final Graph graph) {
        return new CredentialGraph(graph);
    }
}
