/*
 * Copyright 2018 The Hekate Project
 *
 * The Hekate Project 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 io.hekate.coordinate.internal;

import io.hekate.cluster.ClusterHash;
import io.hekate.cluster.ClusterNodeId;
import io.hekate.util.format.ToString;

abstract class CoordinationProtocol {
    enum Type {
        REQUEST,

        RESPONSE,

        REJECT
    }

    static class Request extends CoordinationProtocol {
        private final String processName;

        private final ClusterNodeId from;

        private final ClusterHash topology;

        private final Object request;

        public Request(String processName, ClusterNodeId from, ClusterHash topology, Object request) {
            this.processName = processName;
            this.from = from;
            this.topology = topology;
            this.request = request;
        }

        public String processName() {
            return processName;
        }

        public ClusterNodeId from() {
            return from;
        }

        public ClusterHash topology() {
            return topology;
        }

        public Object request() {
            return request;
        }

        @Override
        public Type type() {
            return Type.REQUEST;
        }
    }

    static class Response extends CoordinationProtocol {
        private final String processName;

        private final Object response;

        public Response(String processName, Object response) {
            this.processName = processName;
            this.response = response;
        }

        public String processName() {
            return processName;
        }

        public Object response() {
            return response;
        }

        @Override
        public Type type() {
            return Type.RESPONSE;
        }
    }

    static final class Reject extends CoordinationProtocol {
        static final Reject INSTANCE = new Reject();

        private Reject() {
            // No-op.
        }

        @Override
        public Type type() {
            return Type.REJECT;
        }
    }

    public abstract Type type();

    @Override
    public String toString() {
        return ToString.format(this);
    }
}

@@ -785,16 +785,94 @@
 oString;
+%0Aimport io.hekate.util.trace.TraceInfo;%0Aimport io.hekate.util.trace.Traceable;
 %0A%0Aabstra
@@ -897,24 +897,45 @@
 ionProtocol 
+implements Traceable 
 %7B%0A    enum T
@@ -1876,32 +1876,247 @@
 QUEST;%0A        %7D
+%0A%0A        @Override%0A        public TraceInfo traceInfo() %7B%0A            return TraceInfo.of(%22/%22 + processName + %22/%22 + request.getClass().getSimpleName())%0A                .withTag(%22topology-hash%22, topology);%0A        %7D
 %0A    %7D%0A%0A    stat
@@ -2641,32 +2641,139 @@
 PONSE;%0A        %7D
+%0A%0A        @Override%0A        public TraceInfo traceInfo() %7B%0A            return TraceInfo.of(%22ok%22);%0A        %7D
 %0A    %7D%0A%0A    stat
@@ -3019,32 +3019,143 @@
 EJECT;%0A        %7D
+%0A%0A        @Override%0A        public TraceInfo traceInfo() %7B%0A            return TraceInfo.of(%22reject%22);%0A        %7D
 %0A    %7D%0A%0A    publ

Add tracing details to CoordinationProtocol.