/*
 * 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.ignite.internal;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.UUID;
import org.apache.ignite.internal.util.distributed.DistributedProcess;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteUuid;
import org.jetbrains.annotations.Nullable;

/**
 * Communication topic.
 */
public enum GridTopic {
    /** */
    TOPIC_JOB,

    /** */
    TOPIC_JOB_SIBLINGS,

    /** */
    TOPIC_TASK,

    /** */
    TOPIC_CHECKPOINT,

    /** */
    TOPIC_JOB_CANCEL,

    /** */
    TOPIC_TASK_CANCEL,

    /** */
    TOPIC_CLASSLOAD,

    /** */
    TOPIC_EVENT,

    /** Cache topic. */
    TOPIC_CACHE,

    /** */
    TOPIC_COMM_USER,

    /** */
    TOPIC_REST,

    /** */
    TOPIC_REPLICATION,

    /**
     * @deprecated Component was removed. Enum can't be removed because enum ordinal is important.
     */
    @Deprecated
    TOPIC_IGFS,

    /** */
    TOPIC_DATASTREAM,

    /** */
    TOPIC_STREAM,

    /** */
    TOPIC_CONTINUOUS,

    /**
     * @deprecated Should be removed in Apache Ignite 3.0.
     */
    @Deprecated
    TOPIC_MONGO,

    /** */
    TOPIC_TIME_SYNC,

    /**
     * @deprecated Component was removed. Enum can't be removed because enum ordinal is important.
     */
    @Deprecated
    TOPIC_HADOOP,

    /** */
    TOPIC_QUERY,

    /** */
    TOPIC_TX,

    /** */
    TOPIC_SNAPSHOT,

    /** */
    TOPIC_IO_TEST,

    /** */
    TOPIC_MAPPING_MARSH,

    /** */
    TOPIC_HADOOP_MSG,

    /** */
    TOPIC_METADATA_REQ,

    /** */
    TOPIC_SCHEMA,

    /** */
    TOPIC_INTERNAL_DIAGNOSTIC,

    /** */
    TOPIC_WAL,

    /** */
    TOPIC_METRICS,

    /** */
    TOPIC_AUTH,

    /** */
    TOPIC_EXCHANGE,

    /** */
    TOPIC_CACHE_COORDINATOR,

    /** */
    TOPIC_GEN_ENC_KEY,

    /** */
    TOPIC_SERVICES,

    /** */
    TOPIC_DEADLOCK_DETECTION,

    /** Message topic for the distributed process. See {@link DistributedProcess}. */
    TOPIC_DISTRIBUTED_PROCESS,

    /** */
    TOPIC_COMM_SYSTEM;

    /** Enum values. */
    private static final GridTopic[] VALS = values();

    /** Default charset to work with strings. */
    private static final Charset DFLT_CHARSET = Charset.forName("UTF-8");

    /**
     * Efficiently gets enumerated value from its ordinal.
     *
     * @param ord Ordinal value.
     * @return Enumerated value.
     */
    @Nullable public static GridTopic fromOrdinal(int ord) {
        return ord >= 0 && ord < VALS.length ? VALS[ord] : null;
    }

    /**
     * @param id Topic ID.
     * @return Grid message topic with specified ID.
     */
    public Object topic(IgniteUuid id) {
        return new T1(this, id);
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(IgniteUuid id1, UUID id2) {
        return new T2(this, id1, id2);
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(IgniteUuid id1, long id2) {
        return new T8(this, id1, id2);
    }

    /**
     * NOTE: The method should be used only for cases when there is no any other non-string identifier(s)
     * to use to differentiate topics.
     *
     * @param id Topic ID.
     * @return Grid message topic with specified ID.
     */
    public Object topic(String id) {
        return new T3(this, UUID.nameUUIDFromBytes(id.getBytes(DFLT_CHARSET)));
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(String id1, long id2) {
        return new T6(this, UUID.nameUUIDFromBytes(id1.getBytes(DFLT_CHARSET)), id2);
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @param id3 ID3.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(String id1, int id2, long id3) {
        return new T5(this, UUID.nameUUIDFromBytes(id1.getBytes(DFLT_CHARSET)), id2, id3);
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @param id3 ID3.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(String id1, UUID id2, long id3) {
        return new T4(this, UUID.nameUUIDFromBytes(id1.getBytes(DFLT_CHARSET)), id2, id3);
    }

    /**
     * @param id1 ID1.
     * @param id2 ID2.
     * @param id3 ID3.
     * @param id4 ID4.
     * @return Grid message topic with specified IDs.
     */
    public Object topic(String id1, UUID id2, int id3, long id4) {
        return new T7(this, UUID.nameUUIDFromBytes(id1.getBytes(DFLT_CHARSET)), id2, id3, id4);
    }

    /**
     *
     */
    private static class T1 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private IgniteUuid id;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T1() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id ID.
         */
        private T1(GridTopic topic, IgniteUuid id) {
            this.topic = topic;
            this.id = id;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id.hashCode();
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T1.class) {
                T1 that = (T1)obj;

                return topic == that.topic && id.equals(that.id);
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeIgniteUuid(out, id);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id = U.readIgniteUuid(in);
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T1.class, this);
        }
    }

    /**
     *
     */
    private static class T2 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private IgniteUuid id1;

        /** */
        private UUID id2;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T2() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         * @param id2 ID2.
         */
        private T2(GridTopic topic, IgniteUuid id1, UUID id2) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + id2.hashCode();
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T2.class) {
                T2 that = (T2)obj;

                return topic == that.topic && id1.equals(that.id1) && id2.equals(that.id2);
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeIgniteUuid(out, id1);
            U.writeUuid(out, id2);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readIgniteUuid(in);
            id2 = U.readUuid(in);
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T2.class, this);
        }
    }

    /**
     *
     */
    private static class T3 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private UUID id1;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T3() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         */
        private T3(GridTopic topic, UUID id1) {
            this.topic = topic;
            this.id1 = id1;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode();
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T3.class) {
                T3 that = (T3)obj;

                return topic == that.topic && id1.equals(that.id1);
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeUuid(out, id1);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readUuid(in);
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T3.class, this);
        }
    }

    /**
     *
     */
    private static class T4 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private UUID id1;

        /** */
        private UUID id2;

        /** */
        private long id3;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T4() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         * @param id2 ID2.
         * @param id3 ID3.
         */
        private T4(GridTopic topic, UUID id1, UUID id2, long id3) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
            this.id3 = id3;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + id2.hashCode() + (int)(id3 ^ (id3 >>> 32));
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T4.class) {
                T4 that = (T4)obj;

                return topic == that.topic && id1.equals(that.id1) && id2.equals(that.id2) && id3 == that.id3;
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeUuid(out, id1);
            U.writeUuid(out, id2);
            out.writeLong(id3);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readUuid(in);
            id2 = U.readUuid(in);
            id3 = in.readLong();
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T4.class, this);
        }
    }

    /**
     *
     */
    private static class T5 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private UUID id1;

        /** */
        private int id2;

        /** */
        private long id3;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T5() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         * @param id2 ID2.
         * @param id3 ID3.
         */
        private T5(GridTopic topic, UUID id1, int id2, long id3) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
            this.id3 = id3;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + id2 + (int)(id3 ^ (id3 >>> 32));
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T5.class) {
                T5 that = (T5)obj;

                return topic == that.topic && id1.equals(that.id1) && id2 == that.id2 && id3 == that.id3;
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeUuid(out, id1);
            out.writeInt(id2);
            out.writeLong(id3);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readUuid(in);
            id2 = in.readInt();
            id3 = in.readLong();
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T5.class, this);
        }
    }

    /**
     *
     */
    private static class T6 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private UUID id1;

        /** */
        private long id2;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T6() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID 1.
         * @param id2 ID 2.
         */
        private T6(GridTopic topic, UUID id1, long id2) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + (int)(id2 ^ (id2 >>> 32));
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T6.class) {
                T6 that = (T6)obj;

                return topic == that.topic && id1.equals(that.id1) && id2 == that.id2;
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeUuid(out, id1);
            out.writeLong(id2);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readUuid(in);
            id2 = in.readLong();
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T6.class, this);
        }
    }

    /**
     *
     */
    private static class T7 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private UUID id1;

        /** */
        private UUID id2;

        /** */
        private int id3;

        /** */
        private long id4;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T7() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         * @param id2 ID2.
         * @param id3 ID3.
         * @param id4 ID4.
         */
        private T7(GridTopic topic, UUID id1, UUID id2, int id3, long id4) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
            this.id3 = id3;
            this.id4 = id4;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + id2.hashCode() + id3 + (int)(id4 ^ (id4 >>> 32));
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T7.class) {
                T7 that = (T7)obj;

                return topic == that.topic && id1.equals(that.id1) && id2.equals(that.id2) && id3 == that.id3 &&
                    id4 == that.id4;
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeUuid(out, id1);
            U.writeUuid(out, id2);
            out.writeInt(id3);
            out.writeLong(id4);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readUuid(in);
            id2 = U.readUuid(in);
            id3 = in.readInt();
            id4 = in.readLong();
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T7.class, this);
        }
    }

    /**
     *
     */
    private static class T8 implements Externalizable {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private GridTopic topic;

        /** */
        private IgniteUuid id1;

        /** */
        private long id2;

        /**
         * No-arg constructor needed for {@link Serializable}.
         */
        public T8() {
            // No-op.
        }

        /**
         * @param topic Topic.
         * @param id1 ID1.
         * @param id2 ID2.
         */
        private T8(GridTopic topic, IgniteUuid id1, long id2) {
            this.topic = topic;
            this.id1 = id1;
            this.id2 = id2;
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return topic.ordinal() + id1.hashCode() + (int)(id2 ^ (id2 >>> 32));
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object obj) {
            if (obj.getClass() == T8.class) {
                T8 that = (T8)obj;

                return topic == that.topic && id1.equals(that.id1) && id2 == that.id2;
            }

            return false;
        }

        /** {@inheritDoc} */
        @Override public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(topic.ordinal());
            U.writeIgniteUuid(out, id1);
            out.writeLong(id2);
        }

        /** {@inheritDoc} */
        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            topic = fromOrdinal(in.readByte());
            id1 = U.readIgniteUuid(in);
            id2 = in.readLong();
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(T8.class, this);
        }
    }
}
