/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF 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 org.apache.geode.redis.internal.netty;

import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

import org.apache.geode.annotations.internal.MakeImmutable;
import org.apache.geode.redis.internal.data.ByteArrayWrapper;

/**
 * This is a safe encoder and decoder for all redis matching needs
 */
public class Coder {


  /*
   * Take no chances on char to byte conversions with default charsets on jvms, so we'll hard code
   * the UTF-8 symbol values as bytes here
   */


  /**
   * byte identifier of a bulk string
   */
  public static final byte BULK_STRING_ID = 36; // '$'

  /**
   * byte identifier of an array
   */
  public static final byte ARRAY_ID = 42; // '*'

  /**
   * byte identifier of an error
   */
  public static final byte ERROR_ID = 45; // '-'

  /**
   * byte identifier of an integer
   */
  public static final byte INTEGER_ID = 58; // ':'
  public static final byte NUMBER_1_BYTE = 0x31; // '1'
  /**
   * byte identifier of a simple string
   */
  public static final byte SIMPLE_STRING_ID = 43; // '+'
  public static final String CRLF = "\r\n";
  @MakeImmutable
  public static final byte[] CRLFar = stringToBytes(CRLF); // {13, 10} == {'\r', '\n'}

  /**
   * byte array of a nil response
   */
  @MakeImmutable
  public static final byte[] bNIL = stringToBytes("$-1\r\n"); // {'$', '-', '1', '\r', '\n'};

  /**
   * byte array of an empty array
   */
  @MakeImmutable
  public static final byte[] bEMPTY_ARRAY = stringToBytes("*0\r\n"); // {'*', '0', '\r', '\n'};

  /**
   * byte array of an empty string
   */
  @MakeImmutable
  public static final byte[] bEMPTY_STRING = stringToBytes("$0\r\n\r\n");

  @MakeImmutable
  public static final byte[] err = stringToBytes("ERR ");
  @MakeImmutable
  public static final byte[] wrongType = stringToBytes("WRONGTYPE ");

  /**
   * The charset being used by this coder, {@value #CHARSET}.
   */
  public static final String CHARSET = "UTF-8";

  @MakeImmutable
  protected static final DecimalFormat decimalFormatter = new DecimalFormat("#");

  static {
    decimalFormatter.setMaximumFractionDigits(10);
  }

  /**
   * Positive infinity string
   */
  public static final String P_INF = "+inf";

  /**
   * Negative infinity string
   */
  public static final String N_INF = "-inf";

  public static ByteBuf getBulkStringResponse(ByteBufAllocator alloc, Object v)
      throws CoderException {
    ByteBuf response;
    byte[] toWrite;

    if (v == null) {
      response = alloc.buffer();
      response.writeBytes(bNIL);
    } else if (v instanceof byte[]) {
      byte[] value = (byte[]) v;
      response = alloc.buffer(value.length + 20);
      toWrite = value;
      writeStringResponse(response, toWrite);
    } else if (v instanceof ByteArrayWrapper) {
      byte[] value = ((ByteArrayWrapper) v).toBytes();
      response = alloc.buffer(value.length + 20);
      toWrite = value;
      writeStringResponse(response, toWrite);
    } else if (v instanceof Double) {
      response = alloc.buffer();
      toWrite = doubleToBytes(((Double) v).doubleValue());
      writeStringResponse(response, toWrite);
    } else if (v instanceof String) {
      String value = (String) v;
      response = alloc.buffer(value.length() + 20);
      toWrite = stringToBytes(value);
      writeStringResponse(response, toWrite);
    } else if (v instanceof Integer) {
      response = alloc.buffer(15);
      response.writeByte(INTEGER_ID);
      response.writeBytes(intToBytes((Integer) v));
      response.writeBytes(CRLFar);
    } else if (v instanceof Long) {
      response = alloc.buffer(15);
      response.writeByte(INTEGER_ID);
      response.writeBytes(intToBytes(((Long) v).intValue()));
      response.writeBytes(CRLFar);
    } else {
      throw new CoderException();
    }

    return response;
  }

  private static void writeStringResponse(ByteBuf response, byte[] toWrite) {
    response.writeByte(BULK_STRING_ID);
    response.writeBytes(intToBytes(toWrite.length));
    response.writeBytes(CRLFar);
    response.writeBytes(toWrite);
    response.writeBytes(CRLFar);
  }

  public static ByteBuf getFlattenedArrayResponse(ByteBufAllocator alloc,
      Collection<Collection<?>> items)
      throws CoderException {
    ByteBuf response = alloc.buffer();

    for (Object next : items) {
      writeCollectionOrString(alloc, response, next);
    }

    return response;
  }

  public static ByteBuf getArrayResponse(ByteBufAllocator alloc, Collection<?> items)
      throws CoderException {
    ByteBuf response = alloc.buffer();
    response.writeByte(ARRAY_ID);
    response.writeBytes(intToBytes(items.size()));
    response.writeBytes(CRLFar);
    for (Object next : items) {
      writeCollectionOrString(alloc, response, next);
    }

    return response;
  }

  private static void writeCollectionOrString(ByteBufAllocator alloc, ByteBuf response, Object next)
      throws CoderException {
    ByteBuf tmp = null;
    try {
      if (next instanceof Collection) {
        Collection<?> nextItems = (Collection<?>) next;
        tmp = getArrayResponse(alloc, nextItems);
        response.writeBytes(tmp);
      } else {
        tmp = getBulkStringResponse(alloc, next);
        response.writeBytes(tmp);
      }
    } finally {
      if (tmp != null) {
        tmp.release();
      }
    }
  }

  public static ByteBuf getScanResponse(ByteBufAllocator alloc, BigInteger cursor,
      List<Object> scanResult) {
    ByteBuf response = alloc.buffer();

    response.writeByte(ARRAY_ID);
    response.writeBytes(intToBytes(2));
    response.writeBytes(CRLFar);
    response.writeByte(BULK_STRING_ID);
    byte[] cursorBytes = stringToBytes(cursor.toString());
    response.writeBytes(intToBytes(cursorBytes.length));
    response.writeBytes(CRLFar);
    response.writeBytes(cursorBytes);
    response.writeBytes(CRLFar);
    response.writeByte(ARRAY_ID);
    response.writeBytes(intToBytes(scanResult.size()));
    response.writeBytes(CRLFar);

    for (Object nextObject : scanResult) {
      if (nextObject instanceof String) {
        String next = (String) nextObject;
        response.writeByte(BULK_STRING_ID);
        response.writeBytes(intToBytes(next.length()));
        response.writeBytes(CRLFar);
        response.writeBytes(stringToBytes(next));
        response.writeBytes(CRLFar);
      } else if (nextObject instanceof ByteArrayWrapper) {
        byte[] next = ((ByteArrayWrapper) nextObject).toBytes();
        response.writeByte(BULK_STRING_ID);
        response.writeBytes(intToBytes(next.length));
        response.writeBytes(CRLFar);
        response.writeBytes(next);
        response.writeBytes(CRLFar);
      }
    }
    return response;
  }

  public static ByteBuf getEmptyArrayResponse(ByteBufAllocator alloc) {
    ByteBuf buf = alloc.buffer().writeBytes(bEMPTY_ARRAY);
    return buf;
  }

  public static ByteBuf getEmptyStringResponse(ByteBufAllocator alloc) {
    ByteBuf buf = alloc.buffer().writeBytes(bEMPTY_STRING);
    return buf;
  }

  public static ByteBuf getSimpleStringResponse(ByteBufAllocator alloc, String string) {
    byte[] simpAr = stringToBytes(string);
    return getSimpleStringResponse(alloc, simpAr);
  }

  public static ByteBuf getSimpleStringResponse(ByteBufAllocator alloc, byte[] byteArray) {
    ByteBuf response = alloc.buffer(byteArray.length + 20);
    response.writeByte(SIMPLE_STRING_ID);
    response.writeBytes(byteArray);
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getErrorResponse(ByteBufAllocator alloc, String error) {
    byte[] errorAr = stringToBytes(error);
    ByteBuf response = alloc.buffer(errorAr.length + 25);
    response.writeByte(ERROR_ID);
    response.writeBytes(err);
    response.writeBytes(errorAr);
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getCustomErrorResponse(ByteBufAllocator alloc, String error) {
    byte[] errorAr = stringToBytes(error);
    ByteBuf response = alloc.buffer(errorAr.length + 25);
    response.writeByte(ERROR_ID);
    response.writeBytes(errorAr);
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getWrongTypeResponse(ByteBufAllocator alloc, String error) {
    byte[] errorAr = stringToBytes(error);
    ByteBuf response = alloc.buffer(errorAr.length + 31);
    response.writeByte(ERROR_ID);
    response.writeBytes(wrongType);
    response.writeBytes(errorAr);
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getIntegerResponse(ByteBufAllocator alloc, int integer) {
    ByteBuf response = alloc.buffer(15);
    response.writeByte(INTEGER_ID);
    response.writeBytes(intToBytes(integer));
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getIntegerResponse(ByteBufAllocator alloc, long l) {
    ByteBuf response = alloc.buffer(25);
    response.writeByte(INTEGER_ID);
    response.writeBytes(longToBytes(l));
    response.writeBytes(CRLFar);
    return response;
  }

  public static ByteBuf getDoubleResponse(ByteBufAllocator alloc, double d) {
    ByteBuf response = alloc.buffer();
    writeStringResponse(response, doubleToBytes(d));
    return response;
  }

  public static ByteBuf getNilResponse(ByteBufAllocator alloc) {
    ByteBuf buf = alloc.buffer().writeBytes(bNIL);
    return buf;
  }


  public static String bytesToString(byte[] bytes) {
    if (bytes == null) {
      return null;
    }
    return new String(bytes);
  }

  public static String doubleToString(double d) {
    if (d == Double.POSITIVE_INFINITY) {
      return "Infinity";
    }
    if (d == Double.NEGATIVE_INFINITY) {
      return "-Infinity";
    }

    String stringValue = String.valueOf(d);
    if (stringValue.endsWith(".0")) {
      return (stringValue.substring(0, stringValue.length() - 2));
    }
    return stringValue;
  }

  public static byte[] stringToBytes(String string) {
    if (string == null) {
      return null;
    }
    return string.getBytes();
  }

  /*
   * These toByte methods convert to byte arrays of the string representation of the input, not
   * literal to byte
   */

  public static byte[] intToBytes(int i) {
    return stringToBytes(String.valueOf(i));
  }

  public static byte[] longToBytes(long l) {
    return stringToBytes(String.valueOf(l));
  }

  public static byte[] doubleToBytes(double d) {
    return stringToBytes(doubleToString(d));
  }

  public static int bytesToInt(byte[] bytes) {
    return Integer.parseInt(bytesToString(bytes));
  }

  public static long bytesToLong(byte[] bytes) {
    return Long.parseLong(bytesToString(bytes));
  }

  /**
   * A conversion where the byte array actually represents a string, so it is converted as a string
   * not as a literal double
   *
   * @param bytes Array holding double
   * @return Parsed value
   * @throws NumberFormatException if bytes to string does not yield a convertible double
   */
  public static double bytesToDouble(byte[] bytes) {
    return stringToDouble(bytesToString(bytes));
  }

  /**
   * Redis specific manner to parse floats
   *
   * @param d String holding double
   * @return Value of string
   * @throws NumberFormatException if the double cannot be parsed
   */
  public static double stringToDouble(String d) {
    if (d.equalsIgnoreCase(P_INF)) {
      return Double.POSITIVE_INFINITY;
    } else if (d.equalsIgnoreCase(N_INF)) {
      return Double.NEGATIVE_INFINITY;
    } else {
      return Double.parseDouble(d);
    }
  }
}
