package org.beigesoft.web.service;

/*
 * Beigesoft ™
 *
 * Licensed under the Apache License, Version 2.0
 *
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 */

import java.io.Reader;
import java.util.Date;
import java.text.SimpleDateFormat;

/**
 * <p>JSP utilities.
 * TODO replace with services (interfaces).
 * </p>
 *
 * @author Yury Demidenko
 */
public class UtlJsp {

  /**
   * <p>Convert source from Reader to JSON string.
   * I.e. replace new lines with '\n' (U+000A) and so on.
   * It also close Reader cause it's assumed
   * to be used it a JSP page.
   * JSP make a lot of userless new lines, spaces,
   * so they will be removed</p>
   * @param source to be converted
   * @return String JSON adapted
   * @throws Exception an exception
   **/
  public final String toJsonStringAndClose(
    final Reader source) throws Exception {
    StringBuffer sb = new StringBuffer();
    int chi;
    boolean isStartSpaces = false;
    while ((chi = source.read()) != -1) {
      char ch = (char) chi;
      isStartSpaces = addJsonChar(ch, sb, isStartSpaces);
    }
    source.close();
    return sb.toString();
  }

  /**
   * <p>Convert string to JSON string.
   * I.e. replace new lines with '\n' (U+000A) and so on.
   * It also close Reader cause it's assumed
   * to be used it a JSP page.
   * JSP make a lot of userless new lines, spaces,
   * so they will be removed</p>
   * @param source to be converted
   * @return String JSON adapted
   * @throws Exception an exception
   **/
  public final String toJsonString(
    final String source) throws Exception {
    StringBuffer sb = new StringBuffer();
    boolean isStartSpaces = false;
    for (int i = 0; i < source.length(); i++) {
      char ch = source.charAt(i);
      isStartSpaces = addJsonChar(ch, sb, isStartSpaces);
    }
    return sb.toString();
  }

  /**
   * <p>Adapt char to Json and add into stringbuffer.</p>
   * @param pCh to be adapted
   * @param pSb StringBuffer
   * @param pIsStartSpaces if it is start/continue spaces
   * @return if it is start/continue spaces
    **/
  public final boolean addJsonChar(final char pCh,
    final StringBuffer pSb, final boolean pIsStartSpaces) {
    boolean isStartSpaces;
    if (pCh == ' ') {
      if (!pIsStartSpaces) {
        isStartSpaces = true;
      } else {
        return true; //it's continue spaces, so remove them
      }
    } else {
      isStartSpaces = false;
    }
    if (!isUseless(pCh)) { //JSP make a lot of useless new lines,
      //so they will be removed
      if (isJsonAdaptable(pCh)) {
        pSb.append('\\');
      }
      pSb.append(pCh);
    }
    return isStartSpaces;
  }

  /**
   * <p>Check if character is useless
   * cause generated by JSP.</p>
   * @param ch char to check
   * @return if need to adapt
   **/
  public final boolean isUseless(final char ch) {
    return ch == '\n' || ch == '\r';
  }

  /**
   * <p>Check if character need to be JSON adapted.
   * I.e. if it is new line...</p>
   * @param ch char to check
   * @return if need to adapt
   **/
  public final boolean isJsonAdaptable(final char ch) {
    return ch == '"' || ch == '\\' || ch == '/'
        || ch == '\b' || ch == '\f' || ch == '\n'
          || ch == '\r' || ch == '\t';
  }

  /**
   * <p>Remove apostrophes from string.</p>
   * @param pSource string with apostrophes
   * @return String without apos
   **/
  public final String removeApos(final String pSource) {
    return pSource.replace("'", "");
  }

  /**
   * <p>To compare for inside JSP EL.</p>
   * @return String "&gt;"
   **/
  public final String getGt() {
    return ">";
  }

  /**
   * <p>To compare for inside JSP EL.</p>
   * @return String "&lt;"
   **/
  public final String getLt() {
    return "<";
  }

  /**
   * <p>Return either string null if src is null or src with quotes.</p>
   * @param src string
   * @return String null or "[src]"
   **/
  public final String nullOrJsonStr(final String src) {
    if (src == null || src.length() == 0) {
      return "null";
    } else {
      return "\"" + src + "\"";
    }
  }

  /**
   * <p>Convert string of milliseconds into
   * Date ISO8601 "yyyy-MM-dd'T'HH:mm".</p>
   * @param src string
   * @return String date
   **/
  public final String fromMsToDateTimeIso8601(final String src) {
    if (src == null || src.length() == 0) {
      return "";
    } else {
      Long dateLong = Long.valueOf(src);
      Date date = new Date(dateLong);
      return dateTimeToIso8601(date);
    }
  }

  /**
   * <p>Convert date into
   * Date ISO8601 "yyyy-MM-dd'T'HH:mm".</p>
   * @param src date
   * @return String date
   **/
  public final String dateTimeToIso8601(final Date src) {
    if (src == null) {
      return "";
    } else {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
      return df.format(src);
    }
  }

  /**
   * <p>Convert string of milliseconds into
   * Date ISO8601 "yyyy-MM-dd".</p>
   * @param src string
   * @return String date
   **/
  public final String fromMsToDateIso8601(final String src) {
    if (src == null || src.length() == 0) {
      return "";
    } else {
      Long dateLong = Long.valueOf(src);
      Date date = new Date(dateLong);
      return dateToIso8601(date);
    }
  }

  /**
   * <p>Convert date into
   * Date ISO8601 "yyyy-MM-dd".</p>
   * @param src date
   * @return String date
   **/
  public final String dateToIso8601(final Date src) {
    if (src == null) {
      return "";
    } else {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      return df.format(src);
    }
  }

  /**
   * <p>Escape HTML character to UTF-8 for given string.</p>
   * @param pSource string
   * @return String escaped
   **/
  public final String escapeHtml(final String pSource) {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < pSource.length(); i++) {
      char ch = pSource.charAt(i);
      sb.append(htmlEscape(ch));
    }
    return sb.toString();
  }
  /**
   * <p>Escape HTML character to UTF-8 for given character.</p>
   * @param pChar character e.g. '''
   * @return String escaped
   **/
  public final String htmlEscape(final char pChar) {
    if (pChar == '\'') {
      return "%27";
    } else if (pChar == ' ') {
      return "%20";
    } else if (pChar == ',') {
      return "%2C";
    } //TODO all chars
    return String.valueOf(pChar);
  }
}
