/*
 * 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.s2graph.core

import org.apache.s2graph.core.GraphExceptions.IllegalDataTypeException
import org.apache.s2graph.core.mysqls.LabelMeta
import org.apache.s2graph.core.rest.TemplateHelper
import org.apache.s2graph.core.types.{InnerVal, InnerValLike, InnerValLikeWithTs, VertexId}
import org.apache.s2graph.core.utils.logger
import play.api.libs.json._


object JSONParser {

  //TODO: check result notation on bigDecimal.
  def innerValToJsValue(innerVal: InnerValLike, dataType: String): Option[JsValue] = {
    try {
      val dType = InnerVal.toInnerDataType(dataType)
      val jsValue = dType match {
        case InnerVal.STRING => JsString(innerVal.value.asInstanceOf[String])
        case InnerVal.BOOLEAN => JsBoolean(innerVal.value.asInstanceOf[Boolean])
        case InnerVal.BYTE | InnerVal.SHORT | InnerVal.INT | InnerVal.LONG | InnerVal.FLOAT | InnerVal.DOUBLE =>
          //        case t if InnerVal.NUMERICS.contains(t) =>
          innerVal.value match {
            case l: Long => JsNumber(l)
            case i: Int => JsNumber(i)
            case s: Short => JsNumber(s.toLong)
            case b: Byte => JsNumber(b.toLong)
            case f: Float => JsNumber(f.toDouble)
            case d: Double =>
              //              JsNumber(d)
              dType match {
                case InnerVal.BYTE => JsNumber(d.toInt)
                case InnerVal.SHORT => JsNumber(d.toInt)
                case InnerVal.INT => JsNumber(d.toInt)
                case InnerVal.LONG => JsNumber(d.toLong)
                case InnerVal.FLOAT => JsNumber(d.toDouble)
                case InnerVal.DOUBLE => JsNumber(d.toDouble)
                case _ => throw new RuntimeException(s"$innerVal, $dType => $dataType")
              }
            case num: BigDecimal =>
              //              JsNumber(num)
              //              JsNumber(InnerVal.scaleNumber(num.asInstanceOf[BigDecimal], dType))
              dType match {
                case InnerVal.BYTE => JsNumber(num.toInt)
                case InnerVal.SHORT => JsNumber(num.toInt)
                case InnerVal.INT => JsNumber(num.toInt)
                case InnerVal.LONG => JsNumber(num.toLong)
                case InnerVal.FLOAT => JsNumber(num.toDouble)
                case InnerVal.DOUBLE => JsNumber(num.toDouble)
                case _ => throw new RuntimeException(s"$innerVal, $dType => $dataType")
              }
            //              JsNumber(num.toLong)
            case _ => throw new RuntimeException(s"$innerVal, Numeric Unknown => $dataType")
          }
        //          JsNumber(InnerVal.scaleNumber(innerVal.asInstanceOf[BigDecimal], dType))
        case _ => throw new RuntimeException(s"$innerVal, Unknown => $dataType")
      }
      Some(jsValue)
    } catch {
      case e: Exception =>
        logger.info(s"JSONParser.innerValToJsValue: $e")
        None
    }
  }

  //  def innerValToString(innerVal: InnerValLike, dataType: String): String = {
  //    val dType = InnerVal.toInnerDataType(dataType)
  //    InnerVal.toInnerDataType(dType) match {
  //      case InnerVal.STRING => innerVal.toString
  //      case InnerVal.BOOLEAN => innerVal.toString
  //      //      case t if InnerVal.NUMERICS.contains(t)  =>
  //      case InnerVal.BYTE | InnerVal.SHORT | InnerVal.INT | InnerVal.LONG | InnerVal.FLOAT | InnerVal.DOUBLE =>
  //        BigDecimal(innerVal.toString).bigDecimal.toPlainString
  //      case _ => innerVal.toString
  //      //        throw new RuntimeException("innerVal to jsValue failed.")
  //    }
  //  }

  //  def toInnerVal(str: String, dataType: String, version: String): InnerValLike = {
  //    //TODO:
  //    //        logger.error(s"toInnerVal: $str, $dataType, $version")
  //    val s =
  //      if (str.startsWith("\"") && str.endsWith("\"")) str.substring(1, str.length - 1)
  //      else str
  //    val dType = InnerVal.toInnerDataType(dataType)
  //
  //    dType match {
  //      case InnerVal.STRING => InnerVal.withStr(s, version)
  //      //      case t if InnerVal.NUMERICS.contains(t) => InnerVal.withNumber(BigDecimal(s), version)
  //      case InnerVal.BYTE | InnerVal.SHORT | InnerVal.INT | InnerVal.LONG | InnerVal.FLOAT | InnerVal.DOUBLE =>
  //        InnerVal.withNumber(BigDecimal(s), version)
  //      case InnerVal.BOOLEAN => InnerVal.withBoolean(s.toBoolean, version)
  //      case InnerVal.BLOB => InnerVal.withBlob(s.getBytes, version)
  //      case _ =>
  //        //        InnerVal.withStr("")
  //        throw new RuntimeException(s"illegal datatype for string: dataType is $dataType for $s")
  //    }
  //  }
  def isNumericType(dType: String): Boolean = {
    dType == InnerVal.LONG || dType == InnerVal.INT ||
      dType == InnerVal.SHORT || dType == InnerVal.BYTE ||
      dType == InnerVal.FLOAT || dType == InnerVal.DOUBLE
  }

  //TODO: fix this messy parts
  def innerValToAny(innerValLike: InnerValLike, dataType: String): Any = {
    val dType = InnerVal.toInnerDataType(dataType)
    dType match {
      case InnerVal.LONG =>
        innerValLike.value match {
          case b: BigDecimal => b.toLong
          case l: Long => l
          case i: Int => i.toLong
          case f: Float => f.toLong
          case d: Double => d.toLong
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case InnerVal.INT =>
        innerValLike.value match {
          case b: BigDecimal => b.toInt
          case l: Long => l.toInt
          case i: Int => i
          case f: Float => f.toInt
          case d: Double => d.toInt
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case InnerVal.SHORT =>
        innerValLike.value match {
          case b: BigDecimal => b.toShort
          case s: Short => s
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case InnerVal.BYTE =>
        innerValLike.value match {
          case b: BigDecimal => b.toByte
          case b: Byte => b
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case InnerVal.FLOAT =>
        innerValLike.value match {
          case b: BigDecimal => b.toFloat
          case d: Double => d.toFloat
          case f: Float => f
          case l: Long => l.toFloat
          case i: Int => i.toFloat
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case InnerVal.DOUBLE =>
        innerValLike.value match {
          case b: BigDecimal => b.toDouble
          case d: Double => d
          case l: Long => l.toDouble
          case i: Int => i.toDouble
          case f: Float => f.toDouble
          case _ => throw new RuntimeException(s"not supported data type: $innerValLike, ${innerValLike.value.getClass}, $dataType")
        }
      case _ => innerValLike.value
    }
  }

  def toInnerVal(any: Any, dataType: String, version: String): InnerValLike = {
    val dType = InnerVal.toInnerDataType(dataType)
    val isNumeric = isNumericType(dType)
    any match {
      case v: VertexId => v.innerId
      case a: InnerValLike => a
      case n: BigDecimal =>
        if (isNumeric) InnerVal.withNumber(n, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(n.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = BigDecimal, [DataType]: $dataType, [Input]: $any")
      case l: Long =>
        if (isNumeric) InnerVal.withLong(l, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(l.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Long, [DataType]: $dataType, [Input]: $any")
      case i: Int =>
        if (isNumeric) InnerVal.withInt(i, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(i.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Int, [DataType]: $dataType, [Input]: $any")
      case sh: Short =>
        if (isNumeric) InnerVal.withInt(sh.toInt, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(sh.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Short, [DataType]: $dataType, [Input]: $any")
      case b: Byte =>
        if (isNumeric) InnerVal.withInt(b.toInt, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(b.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Byte, [DataType]: $dataType, [Input]: $any")
      case f: Float =>
        if (isNumeric) InnerVal.withFloat(f, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(f.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Float, [DataType]: $dataType, [Input]: $any")
      case d: Double =>
        if (isNumeric) InnerVal.withDouble(d, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(d.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Double, [DataType]: $dataType, [Input]: $any")
      case bl: Boolean =>
        if (dType == InnerVal.BOOLEAN) InnerVal.withBoolean(bl, version)
        else if (dType == InnerVal.STRING) InnerVal.withStr(bl.toString, version)
        else throw new IllegalDataTypeException(s"[ValueType] = Boolean, [DataType]: $dataType, [Input]: $any")
      case _s: String =>
        if (isNumeric) {
          try {
            val s = TemplateHelper.replaceVariable(System.currentTimeMillis(), _s.toString)
            InnerVal.withNumber(BigDecimal(s), version)
          } catch {
            case e: Exception =>
              throw new IllegalDataTypeException(s"[ValueType] = String, [DataType]: $dataType, [Input]: $any")
          }
        } else {
          dType match {
            case InnerVal.BOOLEAN => try {
              InnerVal.withBoolean(_s.toBoolean, version)
            } catch {
              case e: Exception =>
                throw new IllegalDataTypeException(s"[ValueType] = String, [DataType]: boolean, [Input]: $any")
            }
            case InnerVal.STRING => InnerVal.withStr(_s, version)
          }
        }
    }
  }

  def jsValueToInnerVal(jsValue: JsValue, dataType: String, version: String): Option[InnerValLike] = {
    val ret = try {
      val dType = InnerVal.toInnerDataType(dataType.toLowerCase())
      jsValue match {
        case n: JsNumber =>
          dType match {
            case InnerVal.STRING => Some(InnerVal.withStr(jsValue.toString, version))
            //            case t if InnerVal.NUMERICS.contains(t) =>
            case InnerVal.BYTE | InnerVal.SHORT | InnerVal.INT | InnerVal.LONG | InnerVal.FLOAT | InnerVal.DOUBLE =>
              Some(InnerVal.withNumber(n.value, version))
            case _ => None
          }
        case _s: JsString =>
          val s = TemplateHelper.replaceVariable(System.currentTimeMillis(), _s.value)
          dType match {
            case InnerVal.STRING => Some(InnerVal.withStr(s, version))
            case InnerVal.BOOLEAN => Some(InnerVal.withBoolean(s.toBoolean, version))
            //            case t if InnerVal.NUMERICS.contains(t) =>
            case InnerVal.BYTE | InnerVal.SHORT | InnerVal.INT | InnerVal.LONG | InnerVal.FLOAT | InnerVal.DOUBLE =>
              Some(InnerVal.withNumber(BigDecimal(s), version))
            case _ => None
          }
        case b: JsBoolean =>
          dType match {
            case InnerVal.STRING => Some(InnerVal.withStr(b.toString, version))
            case InnerVal.BOOLEAN => Some(InnerVal.withBoolean(b.value, version))
            case _ => None
          }
        case _ =>
          None
      }
    } catch {
      case e: Exception =>
        logger.error(s"jsValueToInnerVal: jsValue = ${jsValue}, dataType = ${dataType}, version = ${version}", e)
        None
    }

    ret
  }

  def anyValToJsValue(value: Any): Option[JsValue] = {
    try {
      val v = value match {
        case null => JsNull
        case l: Long => JsNumber(l)
        case i: Int => JsNumber(i)
        case s: Short => JsNumber(s.toInt)
        case b: Byte => JsNumber(b.toInt)
        case f: Float => JsNumber(f.toDouble)
        case d: Double => JsNumber(d)
        case bd: BigDecimal => if (bd.isValidLong) JsNumber(bd.toLong) else JsNumber(bd)
        case s: String => JsString(s)
        case b: Boolean => JsBoolean(b)
        case _ => throw new RuntimeException(s"$value, ${value.getClass.getName} is not supported data type.")
      }
      Option(v)
    } catch {
      case e: Exception =>
        logger.error(s"anyValToJsValue: $value", e)
        None
    }
  }

  def jsValueToAny(value: JsValue): Option[AnyRef] = {
    try {
      value match {
        case n: JsNumber => Option(n.value)
        case s: JsString => Option(TemplateHelper.replaceVariable(System.currentTimeMillis(), s.value))
        case b: JsBoolean => Option(Boolean.box(b.value))
        case _ => None
      }
    } catch {
      case e: Exception =>
        logger.error(s"jsValueToAny: $value", e)
        None
    }
  }

  def propertiesToJson(props: Map[String, Any],
                       selectColumns: Map[String, Boolean] = Map.empty): Map[String, JsValue] = {
    if (selectColumns.isEmpty) {
      for {
        (k, v) <- props
        jsValue <- anyValToJsValue(v)
      //      labelMeta <- label.metaPropsInvMap.get(k)
      //      innerVal = toInnerVal(v.toString, labelMeta.dataType, labelMeta.)
      } yield {
        k -> jsValue
      }
    } else {
      for {
        (k, _) <- selectColumns
        v <- props.get(k)
        jsValue <- anyValToJsValue(v)
      } yield k -> jsValue
    }
  }

  def jsValueToString(jsValue: JsValue): String = {
    jsValue match {
      case s: JsString => s.value
      case _ => jsValue.toString
    }
  }
  def fromJsonToProperties(jsObject: JsObject): Map[String, Any] = {
    val kvs = for {
      (k, v) <- jsObject.fieldSet
    } yield {
        k -> jsValueToString(v)
      }
    kvs.toMap
  }
}
