/*
 * Copyright 2012-2013 JetBrains s.r.o
 *
 * Licensed 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 jetbrains.jetpad.model.id;

import java.util.HashMap;
import java.util.Map;

public class Coder {
  private static final Map<Character, Integer> ourChToValue = new HashMap<Character, Integer>();
  private static final Map<Integer, Character> ourValueToCh = new HashMap<Integer, Character>();

  private Coder() {
  }

  private static void add(char ch) {
    int index = Coder.ourChToValue.size();
    ourChToValue.put(ch, index);
    ourValueToCh.put(index, ch);
  }

  public static String encode(long l) {
    StringBuilder result = new StringBuilder();
    int base = Coder.ourChToValue.size();
    do {
      char ch = ourValueToCh.get((int) (l % base));
      result.insert(0, ch);
      l = l / base;
    } while (l != 0);

    return result.toString();
  }

  public static long decode(String s) {
    long l = 0;
    int base = Coder.ourChToValue.size();
    for (int i = 0; i < s.length(); i++) {
      char ch = s.charAt(i);
      Integer val = ourChToValue.get(ch);
      if (val == null) throw new IllegalStateException("Unknown character '" + ch + "'");
      l = l * base + val;
      if (l < 0) throw new RuntimeException("Overflow");
    }
    return l;
  }

  static {
    for (char ch = 'A'; ch <= 'Z'; ch++) {
      add(ch);
    }
    for (char ch = 'a'; ch <= 'z'; ch++) {
      add(ch);
    }
    for (char ch = '0'; ch <= '9'; ch++) {
      add(ch);
    }
    add('+');
    add('-');
  }
}


@@ -631,16 +631,41 @@
 el.id;%0A%0A
+import java.util.Arrays;%0A
 import j
@@ -747,184 +747,217 @@
 tic 
-f
 in
-al Map%3CCharacter, Integer%3E ourChToValue = new HashMap%3CCharacter, Integer%3E();%0A  private static final Map%3CInteger, Character%3E ourValueToCh = new HashMap%3CInteger, Character%3E();
+t ourBase = 0;%0A  private static final int%5B%5D ourChToValue = new int%5B255%5D;%0A  private static final char%5B%5D ourValueToCh = new char%5B255%5D;%0A%0A  static %7B%0A    Arrays.fill(ourChToValue, 0, ourChToValue.length, -1);%0A  %7D
 %0A%0A  
@@ -1036,33 +1036,17 @@
 x = 
-Coder.ourChToValue.size()
+ourBase++
 ;%0A  
@@ -1063,23 +1063,20 @@
 alue
-.put(ch,
+%5Bch%5D =
  index
-)
 ;%0A  
@@ -1093,23 +1093,20 @@
 ToCh
-.put(
+%5B
 index
-,
+%5D =
  ch
-)
 ;%0A  
@@ -1215,33 +1215,15 @@
 e = 
-Coder.ourChToValue.size()
+ourBase
 ;%0A  
@@ -1257,21 +1257,17 @@
 alueToCh
-.get(
+%5B
 (int) (l
@@ -1274,17 +1274,17 @@
  %25 base)
-)
+%5D
 ;%0A      
@@ -1458,31 +1458,39 @@
 e = 
-Coder.ourChToValue.size
+ourBase;%0A    int len = s.length
 ();%0A
@@ -1513,26 +1513,19 @@
  0; i %3C 
-s.
 len
-gth()
 ; i++) %7B
@@ -1564,15 +1564,11 @@
     
-I
+i
 nt
-eger
  val
@@ -1586,16 +1586,12 @@
 alue
-.get(ch)
+%5Bch%5D
 ;%0A  
@@ -1609,12 +1609,10 @@
  == 
-null
+-1
 ) th

Optimize decored and coder