package com.firefly.net.tcp.codec.flex.stream.impl;

import com.firefly.net.tcp.codec.flex.stream.Stream;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.firefly.net.tcp.codec.flex.stream.impl.StreamStateTransferMap.Op.RECV_ES;
import static com.firefly.net.tcp.codec.flex.stream.impl.StreamStateTransferMap.Op.SEND_ES;

/**
 * @author Pengtao Qiu
 */
public class StreamStateTransferMap {

    private static final List<Node> rules = new ArrayList<>();

    static {
        Node newStream = new Node();
        newStream.op = SEND_ES;
        newStream.from = Stream.State.OPEN;
        newStream.to = Stream.State.LOCALLY_CLOSED;
        rules.add(newStream);

        newStream = new Node();
        newStream.op = RECV_ES;
        newStream.from = Stream.State.OPEN;
        newStream.to = Stream.State.REMOTELY_CLOSED;
        rules.add(newStream);

        Node locallyClosedStream = new Node();
        locallyClosedStream.op = RECV_ES;
        locallyClosedStream.from = Stream.State.LOCALLY_CLOSED;
        locallyClosedStream.to = Stream.State.CLOSED;
        rules.add(locallyClosedStream);

        Node remotelyClosed = new Node();
        remotelyClosed.op = SEND_ES;
        remotelyClosed.from = Stream.State.REMOTELY_CLOSED;
        remotelyClosed.to = Stream.State.CLOSED;
        rules.add(remotelyClosed);
    }

    public static Stream.State getNextState(Stream.State currentState, Op op) {
        return rules.stream()
                    .filter(node -> node.op == op && node.from == currentState)
                    .map(node -> node.to)
                    .findFirst()
                    .orElseThrow(() -> new IllegalStateException("The stream state error. " + currentState + ", " + op));
    }

    public enum Op {
        SEND_ES, RECV_ES
    }

    private static class Node {
        Op op;
        Stream.State from;
        Stream.State to;
    }


}

@@ -117,25 +117,23 @@
 va.util.
-ArrayList
+HashMap
 ;%0Aimport
@@ -143,20 +143,19 @@
 va.util.
-List
+Map
 ;%0Aimport
@@ -170,15 +170,14 @@
 il.O
-ptional
+bjects
 ;%0A%0Ai
@@ -459,17 +459,30 @@
 nal 
-List
+Map
 %3CNode
+, Stream.State
 %3E ru
@@ -495,17 +495,15 @@
 new 
-ArrayList
+HashMap
 %3C%3E()
@@ -631,32 +631,42 @@
 e.OPEN;%0A        
+rules.put(
 newStream.to = S
@@ -650,37 +650,33 @@
 es.put(newStream
-.to =
+,
  Stream.State.LO
@@ -691,37 +691,8 @@
 OSED
-;%0A        rules.add(newStream
 );%0A%0A
@@ -799,32 +799,42 @@
 e.OPEN;%0A        
+rules.put(
 newStream.to = S
@@ -822,29 +822,25 @@
 ut(newStream
-.to =
+,
  Stream.Stat
@@ -860,37 +860,8 @@
 OSED
-;%0A        rules.add(newStream
 );%0A%0A
@@ -1013,32 +1013,42 @@
 CLOSED;%0A        
+rules.put(
 locallyClosedStr
@@ -1050,21 +1050,17 @@
 edStream
-.to =
+,
  Stream.
@@ -1075,47 +1075,8 @@
 OSED
-;%0A        rules.add(locallyClosedStream
 );%0A%0A
@@ -1214,32 +1214,42 @@
 CLOSED;%0A        
+rules.put(
 remotelyClosed.t
@@ -1250,13 +1250,9 @@
 osed
-.to =
+,
  Str
@@ -1271,42 +1271,8 @@
 OSED
-;%0A        rules.add(remotelyClosed
 );%0A 
@@ -1369,37 +1369,39 @@
     
-return rules.stream
+Node node = new Node
 ()
+;
 %0A       
     
@@ -1400,53 +1400,8 @@
     
-             .filter(node -%3E node.op == op &&
  nod
@@ -1408,17 +1408,16 @@
 e.from =
-=
  current
@@ -1421,17 +1421,17 @@
 entState
-)
+;
 %0A       
@@ -1435,113 +1435,114 @@
     
-            .map(node -%3E node.to)%0A                    .findFirst()%0A                    .orElseThrow(() -%3E
+node.op = op;%0A        Stream.State state = rules.get(node);%0A        if (state == null) %7B%0A            throw
  new
@@ -1618,18 +1618,70 @@
  %22 + op)
-)
 ;
+%0A        %7D else %7B%0A            return state;%0A        %7D
 %0A    %7D%0A%0A
@@ -1807,24 +1807,25 @@
 e from;%0A
+%0A
         
 Stream.S
@@ -1820,24 +1820,373 @@
     
-Stream.State to;
+@Override%0A        public boolean equals(Object o) %7B%0A            if (this == o) return true;%0A            if (o == null %7C%7C getClass() != o.getClass()) return false;%0A            Node node = (Node) o;%0A            return op == node.op && from == node.from;%0A        %7D%0A%0A        @Override%0A        public int hashCode() %7B%0A            return Objects.hash(op, from);%0A        %7D
 %0A   

optimize StreamStateTransferMap