/**
 * 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.netbeans.modules.db.metadata.model.api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.openide.util.Parameters;

/**
 * Represents the handle of a metadata element.
 *
 * <p>Metadata elements cannot escape the {@link MetadataModel#runReadAction} method.
 * Handles can be used to pass information about metadata elements out of this method.
 * The handle can be {@link #resolve resolved} to the corresponding
 * metadata element in another {@code runReadAction} method.</p>
 *
 * @param <T> the type of the metadata element that this handle was created for.
 *
 * @author Andrei Badea
 */
public class MetadataElementHandle<T extends MetadataElement> {

    // These integers place a particular element in the hierarchy of elements,
    // with CATALOG at the top
    private static final int CATALOG = 0;
    private static final int SCHEMA = 1;
    private static final int TABLE = 2;
    private static final int VIEW = 2;
    private static final int PROCEDURE = 2;
    private static final int COLUMN = 3;
    private static final int PARAMETER = 3;
    private static final int INDEX = 3;
    private static final int FOREIGN_KEY = 3;
    private static final int FOREIGN_KEY_COLUMN = 4;
    private static final int INDEX_COLUMN = 4;
    private static final int FUNCTION = 2;

    // The hierarchy of names for this element (e.g. ["mycatalog","myschema","mytable","mycolumn"])
    //
    // It is the combination of the hierarchy of names and kinds that uniquely identifies this
    // element in the metadata model.
    private final String[] names;

    // The hierarchy of element kinds for this element (e.g. [CATALOG,SCHEMA,TABLE,COLUMN]
    // or [CATALOG,SCHEMA,VIEW,COLUMN])
    //
    // It is the combination of the hierarchy of names and kinds that uniquely identifies this
    // element in the metadata model.
    private final Kind[] kinds;

    /**
     * Creates a handle for a metadata element.
     *
     * @param  <T> the type of the metadata element to create this handle for.
     * @param  element a metadata element.
     * @return the handle for the given metadata element.
     */
    public static <T extends MetadataElement> MetadataElementHandle<T> create(T element) {
        Parameters.notNull("element", element);
        List<String> names = new ArrayList<String>();
        List<Kind> kinds = new ArrayList<Kind>();
        MetadataElement current = element;
        while (current != null) {
            names.add(current.getInternalName());
            kinds.add(Kind.of(current));
            current = current.getParent();
        }
        Collections.reverse(names);
        Collections.reverse(kinds);
        String[] namesArray = names.toArray(new String[names.size()]);
        Kind[] kindsArray = kinds.toArray(new Kind[kinds.size()]);

        return new MetadataElementHandle<T>(namesArray,kindsArray);
    }

    // For use in unit tests.
    static <T extends MetadataElement> MetadataElementHandle<T> create(Class<T> clazz, String[] names, Kind[] kinds) {
        return new MetadataElementHandle<T>(names, kinds);
    }

    private MetadataElementHandle(String[] names, Kind[] kinds) {
        this.names = names;
        this.kinds = kinds;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        MetadataElementHandle<?> other = (MetadataElementHandle<?>) obj;
        if (!Arrays.equals(this.kinds, other.kinds)) {
            return false;
        }
        if (!Arrays.equals(this.names, other.names)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        for (String name : names) {
            if (name != null) {
                hash ^= name.hashCode();
            } else {
                // Do not XOR with a constant, since multiple nulls would
                // cause the hash to just flip-flop between two values.
                hash++;
            }
        }
        for (Kind kind : kinds) {
            hash ^= kind.hashCode();
        }
        return hash;
    }

    /**
     * Resolves this handle to the corresponding metadata element, if any.
     *
     * @param  metadata the {@link Metadata} instance to resolve this element against.
     * @return the corresponding metadata element or null if it could not be found
     *         (for example because it is not present in the given {@code Metadata}
     *         instance, or because it has been removed).
     */
    @SuppressWarnings("unchecked")
    public T resolve(Metadata metadata) {
        int length = kinds.length;
        switch (kinds[length - 1]) {
            case CATALOG:
                return (T) resolveCatalog(metadata);
            case SCHEMA:
                return (T) resolveSchema(metadata);
            case TABLE:
                return (T) resolveTable(metadata);
            case VIEW:
                return (T) resolveView(metadata);
            case PROCEDURE:
                return (T) resolveProcedure(metadata);
            case COLUMN:
                return (T) resolveColumn(metadata);
            case PRIMARY_KEY:
                return (T) resolvePrimaryKey(metadata);
            case PARAMETER:
                return (T) resolveParameter(metadata);
            case FOREIGN_KEY:
                return (T) resolveForeignKey(metadata);
            case INDEX:
                return (T) resolveIndex(metadata);
            case FOREIGN_KEY_COLUMN:
                return (T) resolveForeignKeyColumn(metadata);
            case INDEX_COLUMN:
                return (T) resolveIndexColumn(metadata);
            case RETURN_VALUE:
                return (T) resolveReturnValue(metadata);
            case FUNCTION:
                return (T) resolveFunction(metadata);
            default:
                throw new IllegalStateException("Unhandled kind " + kinds[kinds.length -1]);
        }
    }

    private Catalog resolveCatalog(Metadata metadata) {
        return metadata.getCatalog(names[CATALOG]);
    }

    private Schema resolveSchema(Metadata metadata) {
        Catalog catalog = resolveCatalog(metadata);
        if (catalog != null) {
            String name = names[SCHEMA];
            if (name != null) {
                return catalog.getSchema(name);
            } else {
                return catalog.getSyntheticSchema();
            }
        }
        return null;
    }

    private Table resolveTable(Metadata metadata) {
        Schema schema = resolveSchema(metadata);
        if (schema != null) {
            return schema.getTable(names[TABLE]);
        }
        return null;
    }

    private View resolveView(Metadata metadata) {
        Schema schema = resolveSchema(metadata);
        if (schema != null) {
            return schema.getView(names[VIEW]);
        }
        return null;
    }

    private Procedure resolveProcedure(Metadata metadata) {
        Schema schema = resolveSchema(metadata);
        if (schema != null && kinds[PROCEDURE] == Kind.PROCEDURE) {
            return schema.getProcedure(names[PROCEDURE]);
        }
        return null;
    }

    private Function resolveFunction(Metadata metadata) {
        Schema schema = resolveSchema(metadata);
        if (schema != null && kinds[FUNCTION] == Kind.FUNCTION) {
            return schema.getFunction(names[FUNCTION]);
        }
        return null;
    }

    private Value resolveReturnValue(Metadata metadata) {
        Function proc = resolveFunction(metadata);
        if (proc != null) {
            return proc.getReturnValue();
        }
        Procedure proc2 = resolveProcedure(metadata);
        if (proc2 != null) {
            return proc2.getReturnValue();
        }
        return null;
    }

    private PrimaryKey resolvePrimaryKey(Metadata metadata) {
        Table table = resolveTable(metadata);
        if (table != null) {
            return table.getPrimaryKey();
        }

        return null;
    }

    private Column resolveColumn(Metadata metadata) {
        // A column can be part of a number of different metadata elements.
        // Find out which one and resolve appropriately
        switch (kinds[COLUMN - 1]) {
            case TABLE:
                Table table = resolveTable(metadata);
                if (table != null) {
                    return table.getColumn(names[COLUMN]);
                }
                return null;
            case PROCEDURE:
                Procedure proc = resolveProcedure(metadata);
                if (proc != null) {
                    return proc.getColumn(names[COLUMN]);
                }
                return null;
            case VIEW:
                View view = resolveView(metadata);
                if (view != null) {
                    return view.getColumn(names[COLUMN]);
                }
                return null;
            default:
                throw new IllegalStateException("Unhandled kind " + kinds[COLUMN -1]);
        }
    }

    private Parameter resolveParameter(Metadata metadata) {
        Procedure proc = resolveProcedure(metadata);
        if (proc != null) {
            return proc.getParameter(names[PARAMETER]);
        }
        Function proc2 = resolveFunction(metadata);
        if (proc2 != null) {
            return proc2.getParameter(names[PARAMETER]);
        }
        return null;
    }

    private Index resolveIndex(Metadata metadata) {
        Table table = resolveTable(metadata);
        if (table != null) {
            return table.getIndex(names[INDEX]);
        }
        return null;
    }

    private ForeignKey resolveForeignKey(Metadata metadata) {
        Table table = resolveTable(metadata);
        if (table != null) {
            return table.getForeignKeyByInternalName(names[FOREIGN_KEY]);
        }

        return null;
    }

    private ForeignKeyColumn resolveForeignKeyColumn(Metadata metadata) {
        ForeignKey key = resolveForeignKey(metadata);
        if (key != null) {
            return key.getColumn(names[FOREIGN_KEY_COLUMN]);
        }

        return null;
    }

    private IndexColumn resolveIndexColumn(Metadata metadata) {
        Index index = resolveIndex(metadata);
        if (index != null) {
            return index.getColumn(names[INDEX_COLUMN]);
        }

        return null;
    }

    // Not private becuase it's used in unit tests
    enum Kind {

        CATALOG(Catalog.class),
        SCHEMA(Schema.class),
        TABLE(Table.class),
        VIEW(View.class),
        PROCEDURE(Procedure.class),
        PARAMETER(Parameter.class),
        COLUMN(Column.class),
        PRIMARY_KEY(PrimaryKey.class),
        FOREIGN_KEY(ForeignKey.class),
        INDEX(Index.class),
        FOREIGN_KEY_COLUMN(ForeignKeyColumn.class),
        INDEX_COLUMN(IndexColumn.class),
        RETURN_VALUE(Value.class),
        FUNCTION(Function.class);

        public static Kind of(MetadataElement element) {
            return of(element.getClass());
        }

        public static Kind of(Class<? extends MetadataElement> clazz) {
            for (Kind kind : Kind.values()) {
                if (kind.clazz.equals(clazz)) {
                    return kind;
                }
            }
            throw new IllegalStateException("Unhandled class " + clazz);
        }

        private final Class<? extends MetadataElement> clazz;

        private Kind(Class<? extends MetadataElement> clazz) {
            this.clazz = clazz;
        }
    }
}
