package ch.unibe.scg.regex;

import java.util.LinkedHashMap;
import java.util.Map;

interface Instruction {
  public static class Context {}

  static class CopyInstruction implements Instruction {

    public static Instruction make(final int fromTag, final int fromPos, final int toTag,
        final int toPos) {
      return new CopyInstruction(fromTag, fromPos, toTag, toPos);
    }

    final int fromTag, fromPos, toTag, toPos;

    public CopyInstruction(final int fromTag, final int fromPos, final int toTag, final int toPos) {
      this.fromTag = fromTag;
      this.fromPos = fromPos;
      this.toTag = toTag;
      this.toPos = toPos;
    }

    public void execute(final Context context, final int pos) {
      throw null;
    }

    @Override
    public String toString() {
      return "" + fromTag + "," + fromPos + " <- " + toTag + "," + toPos;
    }

  }

  /**
   * Not threadsafe!
   */
  class InstructionMaker {

    public static InstructionMaker get() {
      return new InstructionMaker();
    }

    int id = -1;

    Map<Tag, Integer> tagIds = new LinkedHashMap<>();

    int lookup(final Tag tag) {
      final Integer id = tagIds.get(tag);
      if (id != null) {
        return id;
      }
      final int ret = nextId();
      tagIds.put(tag, ret);
      return ret;

    }

    public int nextId() {
      return ++id;
    }

    public Instruction reorder(final int i, final int j) {
      throw new RuntimeException("Not implemented");
    }

    public Instruction reorder(final MapItem from, final MapItem to) {
      return CopyInstruction.make(lookup(from.getTag()), from.getPos(), lookup(to.getTag()),
          to.getPos());
    }

    public Instruction storePos(final int i) {
      throw new RuntimeException("Not implemented");
    }

    public Instruction storePos(final MapItem mapItem) {
      return SetInstruction.make(lookup(mapItem.getTag()), mapItem.getPos());
    }

  }

  static class SetInstruction implements Instruction {

    static SetInstruction make(final int tag, final int pos) {
      return new SetInstruction(tag, pos);
    }

    final int tag, pos;

    public SetInstruction(final int tag, final int pos) {
      this.tag = tag;
      this.pos = pos;
    }

    public void execute(final Context context, final int pos) {
      throw null;
    }

    @Override
    public String toString() {
      return "" + tag + "," + pos + "<- pos";
    }
  }

  public void execute(Context context, int pos);
}

@@ -104,41 +104,8 @@
 on %7B
-%0A  public static class Context %7B%7D
 %0A%0A  
@@ -154,25 +154,24 @@
 struction %7B%0A
-%0A
     public s
@@ -607,32 +607,46 @@
 = toPos;%0A    %7D%0A%0A
+    @Override%0A
     public void 
@@ -649,37 +649,29 @@
 oid execute(
-f
 in
-al Context
+t%5B%5D
  context, fi
@@ -659,38 +659,32 @@
 e(int%5B%5D context,
- final
  int pos) %7B%0A    
@@ -684,35 +684,70 @@
  %7B%0A      throw n
-ull
+ew RuntimeException(%22Not implemented%22)
 ;%0A    %7D%0A%0A    @Ov
@@ -860,25 +860,24 @@
 oPos;%0A    %7D%0A
-%0A
   %7D%0A%0A  /**%0A 
@@ -929,17 +929,16 @@
 Maker %7B%0A
-%0A
     publ
@@ -1292,17 +1292,16 @@
 rn ret;%0A
-%0A
     %7D%0A%0A 
@@ -1392,17 +1392,20 @@
 nal int 
-i
+from
 , final 
@@ -1408,17 +1408,18 @@
 nal int 
-j
+to
 ) %7B%0A    
@@ -1424,52 +1424,46 @@
     
-throw new RuntimeException(%22Not implemented%22
+return new ReorderInstruction(from, to
 );%0A 
@@ -1549,116 +1549,52 @@
     
-return CopyInstruction.make(lookup(from.getTag()), from.getPos(), lookup(to.getTag()),%0A          to.getPos()
+throw new RuntimeException(%22Not implemented%22
 );%0A 
@@ -1641,17 +1641,19 @@
 nal int 
-i
+tag
 ) %7B%0A    
@@ -1658,52 +1658,38 @@
     
-throw new RuntimeException(%22Not implemented%22
+return SetInstruction.make(tag
 );%0A 
@@ -1812,35 +1812,404 @@
 g())
-, mapItem.getPos())
+);%0A    %7D%0A  %7D%0A%0A  static class ReorderInstruction implements Instruction %7B%0A    final int from, to;%0A%0A    ReorderInstruction(int from, int to) %7B%0A      this.from = from;%0A      this.to = to;%0A    %7D%0A%0A    @Override%0A    public void execute(int%5B%5D context, int pos) %7B%0A      context%5Bto%5D = context%5Bfrom%5D;%0A    %7D%0A%0A    @Override%0A    public String toString() %7B%0A      return String.valueOf(from) + %22-%3E%22 + to
 ;%0A    %7D%0A
 %0A  %7D
@@ -2204,17 +2204,16 @@
 ;%0A    %7D%0A
-%0A
   %7D%0A%0A  s
@@ -2264,17 +2264,16 @@
 ction %7B%0A
-%0A
     stat
@@ -2304,39 +2304,24 @@
 inal int tag
-, final int pos
 ) %7B%0A      re
@@ -2347,21 +2347,16 @@
 tion(tag
-, pos
 );%0A    %7D
@@ -2378,13 +2378,8 @@
  tag
-, pos
 ;%0A%0A 
@@ -2416,31 +2416,16 @@
  int tag
-, final int pos
 ) %7B%0A    
@@ -2446,30 +2446,8 @@
 ag;%0A
-      this.pos = pos;%0A
     
@@ -2479,23 +2479,21 @@
 e(final 
-Context
+int%5B%5D
  context
@@ -2521,18 +2521,26 @@
     
-throw null
+context%5Btag%5D = pos
 ;%0A  
@@ -2616,20 +2616,8 @@
 ag +
- %22,%22 + pos +
  %22%3C-
@@ -2660,15 +2660,13 @@
 ute(
-Context
+int%5B%5D
  con

Implement set instructions.