/*
 * 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_GEN_ENC_KEY,

    /** */
    TOPIC_SERVICES,

    /** */
    TOPIC_DEADLOCK_DETECTION,

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

    /** */
    TOPIC_COMM_SYSTEM,

    /** Statistics related messages topic. */
    TOPIC_STATISTICS;

    /** 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);
        }
    }
}
