package net.ihiroky.niotty;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created on 13/01/09, 17:24
 *
 * @author Hiroki Itoh
 */
public abstract class StageContext<I, O> {

    private Pipeline pipeline_;
    private I message_;
    private StageContext<O, Object> next_;
    private StageContextListener<I, O> listener_;

    private static final StageContextListener<Object, Object> NULL_LISTENER = new StageContextAdapter<>();

    @SuppressWarnings("unchecked")
    private static <I, O> StageContextListener<I, O> nullListener() {
        return (StageContextListener<I, O>) NULL_LISTENER;
    }

    protected StageContext(Pipeline pipeline) {
        this.pipeline_ = pipeline;
        this.listener_ = nullListener();
    }

    protected StageContext<O, Object> next() {
        return next_;
    }

    protected void setNext(StageContext<O, Object> next) {
        Objects.requireNonNull(next, "next");
        this.next_ = next;
    }

    public I message() {
        return message_;
    }

    public Transport transport() {
        return pipeline_.transport();
    }

    public void proceed(O output) {
        listener_.onProceed(pipeline_, this, output);
        next_.fire(output);

    }

    public void proceed(TransportStateEvent event) {
        listener_.onProceed(pipeline_, this, event);
        next_.fire(event);
    }

    protected void callOnFire(I input) {
        listener_.onFire(pipeline_, this, input);
    }

    protected void callOnFire(TransportStateEvent event) {
        listener_.onFire(pipeline_, this, event);
    }

    public void addListener(StageContextListener<?, ?> contextListener) {
        Objects.requireNonNull(contextListener, "contextListener");

        StageContextListener<I, O> oldListener = listener_;
        @SuppressWarnings("unchecked")
        StageContextListener<I, O> newListener = (StageContextListener<I, O>) contextListener;

        if (listener_ == NULL_LISTENER) {
            listener_ = newListener;
            return;
        }
        if (listener_ instanceof ListenerList) {
            ((ListenerList<I, O>) listener_).list.add(newListener);
            return;
        }

        ListenerList<I, O> listenerList = new ListenerList<>();
        listenerList.list.add(oldListener);
        listenerList.list.add(newListener);
        listener_ = listenerList;
    }

    protected StageContextListener<I, O> getListener() {
        return listener_;
    }

    private static class ListenerList<I, O> implements StageContextListener<I, O> {

        List<StageContextListener<I, O>> list = new CopyOnWriteArrayList<>();

        @Override
        public void onFire(Pipeline pipeline, StageContext<I, O> context, I input) {
            for (StageContextListener<I, O> listener : list) {
                listener.onFire(pipeline, context, input);
            }
        }

        @Override
        public void onFire(Pipeline pipeline, StageContext<I, O> context, TransportStateEvent event) {
            for (StageContextListener<I, O> listener : list) {
                listener.onFire(pipeline, context, event);
            }
        }

        @Override
        public void onProceed(Pipeline pipeline, StageContext<I, O> context, O output) {
            for (StageContextListener<I, O> listener : list) {
                listener.onProceed(pipeline, context, output);
            }
        }

        @Override
        public void onProceed(Pipeline pipeline, StageContext<I, O> context, TransportStateEvent event) {
            for (StageContextListener<I, O> listener : list) {
                listener.onProceed(pipeline, context, event);
            }
        }
    }

    protected abstract Object getStage();
    protected abstract void fire(I input);
    protected abstract void fire(TransportStateEvent event);
}

@@ -266,32 +266,8 @@
 e_;%0A
-    private I message_;%0A
     
@@ -985,65 +985,8 @@
  %7D%0A%0A
-    public I message() %7B%0A        return message_;%0A    %7D%0A%0A
     

Remove unused code