/*
 * 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.cassandra.auth;

import java.util.Set;

import com.google.common.base.Objects;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;

import org.apache.cassandra.config.Schema;

/**
 * The primary type of resource in Cassandra.
 *
 * Used to represent a table or a keyspace or the root level "data" resource.
 * "data"                                 - the root level data resource.
 * "data/keyspace_name"                   - keyspace-level data resource.
 * "data/keyspace_name/table_name"        - table-level data resource.
 */
public class DataResource implements IResource
{
    enum Level
    {
        ROOT, KEYSPACE, TABLE
    }

    // permissions which may be granted on tables
    private static final Set<Permission> TABLE_LEVEL_PERMISSIONS = Sets.immutableEnumSet(Permission.ALTER,
                                                                                         Permission.DROP,
                                                                                         Permission.SELECT,
                                                                                         Permission.MODIFY,
                                                                                         Permission.AUTHORIZE);
    // permissions which may be granted on one or all keyspaces
    private static final Set<Permission> KEYSPACE_LEVEL_PERMISSIONS = Sets.immutableEnumSet(Permission.CREATE,
                                                                                            Permission.ALTER,
                                                                                            Permission.DROP,
                                                                                            Permission.SELECT,
                                                                                            Permission.MODIFY,
                                                                                            Permission.AUTHORIZE);
    private static final String ROOT_NAME = "data";
    private static final DataResource ROOT_RESOURCE = new DataResource();

    private final Level level;
    private final String keyspace;
    private final String table;

    private DataResource()
    {
        level = Level.ROOT;
        keyspace = null;
        table = null;
    }

    private DataResource(String keyspace)
    {
        level = Level.KEYSPACE;
        this.keyspace = keyspace;
        table = null;
    }

    private DataResource(String keyspace, String table)
    {
        level = Level.TABLE;
        this.keyspace = keyspace;
        this.table = table;
    }

    /**
     * @return the root-level resource.
     */
    public static DataResource root()
    {
        return ROOT_RESOURCE;
    }

    /**
     * Creates a DataResource representing a keyspace.
     *
     * @param keyspace Name of the keyspace.
     * @return DataResource instance representing the keyspace.
     */
    public static DataResource keyspace(String keyspace)
    {
        return new DataResource(keyspace);
    }

    /**
     * Creates a DataResource instance representing a table.
     *
     * @param keyspace Name of the keyspace.
     * @param table Name of the table.
     * @return DataResource instance representing the column family.
     */
    public static DataResource table(String keyspace, String table)
    {
        return new DataResource(keyspace, table);
    }

    /**
     * Parses a data resource name into a DataResource instance.
     *
     * @param name Name of the data resource.
     * @return DataResource instance matching the name.
     */
    public static DataResource fromName(String name)
    {
        String[] parts = StringUtils.split(name, '/');

        if (!parts[0].equals(ROOT_NAME) || parts.length > 3)
            throw new IllegalArgumentException(String.format("%s is not a valid data resource name", name));

        if (parts.length == 1)
            return root();

        if (parts.length == 2)
            return keyspace(parts[1]);

        return table(parts[1], parts[2]);
    }

    /**
     * @return Printable name of the resource.
     */
    public String getName()
    {
        switch (level)
        {
            case ROOT:
                return ROOT_NAME;
            case KEYSPACE:
                return String.format("%s/%s", ROOT_NAME, keyspace);
            case TABLE:
                return String.format("%s/%s/%s", ROOT_NAME, keyspace, table);
        }
        throw new AssertionError();
    }

    /**
     * @return Parent of the resource, if any. Throws IllegalStateException if it's the root-level resource.
     */
    public IResource getParent()
    {
        switch (level)
        {
            case KEYSPACE:
                return root();
            case TABLE:
                return keyspace(keyspace);
        }
        throw new IllegalStateException("Root-level resource can't have a parent");
    }

    public boolean isRootLevel()
    {
        return level == Level.ROOT;
    }

    public boolean isKeyspaceLevel()
    {
        return level == Level.KEYSPACE;
    }

    public boolean isTableLevel()
    {
        return level == Level.TABLE;
    }
    /**
     * @return keyspace of the resource. Throws IllegalStateException if it's the root-level resource.
     */
    public String getKeyspace()
    {
        if (isRootLevel())
            throw new IllegalStateException("ROOT data resource has no keyspace");
        return keyspace;
    }

    /**
     * @return column family of the resource. Throws IllegalStateException if it's not a table-level resource.
     */
    public String getTable()
    {
        if (!isTableLevel())
            throw new IllegalStateException(String.format("%s data resource has no table", level));
        return table;
    }

    /**
     * @return Whether or not the resource has a parent in the hierarchy.
     */
    public boolean hasParent()
    {
        return level != Level.ROOT;
    }

    /**
     * @return Whether or not the resource exists in Cassandra.
     */
    public boolean exists()
    {
        switch (level)
        {
            case ROOT:
                return true;
            case KEYSPACE:
                return Schema.instance.getKeyspaces().contains(keyspace);
            case TABLE:
                return Schema.instance.getCFMetaData(keyspace, table) != null;
        }
        throw new AssertionError();
    }

    public Set<Permission> applicablePermissions()
    {
        switch (level)
        {
            case ROOT:
            case KEYSPACE:
                return KEYSPACE_LEVEL_PERMISSIONS;
            case TABLE:
                return TABLE_LEVEL_PERMISSIONS;
        }
        throw new AssertionError();
    }

    @Override
    public String toString()
    {
        switch (level)
        {
            case ROOT:
                return "<all keyspaces>";
            case KEYSPACE:
                return String.format("<keyspace %s>", keyspace);
            case TABLE:
                return String.format("<table %s.%s>", keyspace, table);
        }
        throw new AssertionError();
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;

        if (!(o instanceof DataResource))
            return false;

        DataResource ds = (DataResource) o;

        return Objects.equal(level, ds.level)
            && Objects.equal(keyspace, ds.keyspace)
            && Objects.equal(table, ds.table);
    }

    @Override
    public int hashCode()
    {
        return Objects.hashCode(level, keyspace, table);
    }
}
