/*
 * 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.mysqls.LabelMeta
import org.apache.s2graph.core.types.{CanInnerValLike, InnerValLikeWithTs, VertexId}
import org.apache.tinkerpop.gremlin.structure.Graph.Features
import org.apache.tinkerpop.gremlin.structure.util.ElementHelper
import org.apache.tinkerpop.gremlin.structure._

import scala.util.hashing.MurmurHash3

object S2Property {

  def validType(t: Any): Boolean = t match {
    case _: EdgeId => true
    case _: VertexId => true
    case _: java.lang.Integer => true
    case _: java.lang.Long => true
    case _: java.lang.Float => true
    case _: java.lang.Double => true
    case _: java.lang.Boolean => true
    case _: java.lang.Short => true
    case _: java.lang.Byte => true
    case _: java.lang.String => true
    case _: java.math.BigDecimal => true
    case _: Int => true
    case _: Long => true
    case _: Float => true
    case _: Double => true
    case _: Boolean => true
    case _: Short => true
    case _: Byte => true
    case _: BigDecimal => true
    case _ => false
  }

  def kvsToProps(kvs: Seq[AnyRef]): Map[String, AnyRef] = {
    import scala.collection.JavaConverters._

    ElementHelper.legalPropertyKeyValueArray(kvs: _*)
    val keySet = collection.mutable.Set[Any]()
    val kvsList = ElementHelper.asPairs(kvs: _*).asScala
    var result = Map[String, AnyRef]()
    kvsList.foreach { pair =>
      val key = pair.getValue0
      val value = pair.getValue1 match {
        case v: java.math.BigDecimal => new BigDecimal(v)
        case _@org => org
      }

      ElementHelper.validateProperty(key, value)
//      if (keySet.contains(key)) throw VertexProperty.Exceptions.multiPropertiesNotSupported

//      assertValidProp(key, value)

      keySet.add(key)
      result = result + (key -> value)
    }

    result
  }

  def assertValidProp[A](key: Any, value: A): Unit = {
    if (key == null) throw Property.Exceptions.propertyKeyCanNotBeEmpty()
    if (!key.isInstanceOf[String]) throw Element.Exceptions.providedKeyValuesMustHaveALegalKeyOnEvenIndices()

    if (value == null) throw Property.Exceptions.propertyValueCanNotBeNull()
    if (!validType(value)) {
     value match {
       case _: java.io.Serializable => throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(value)
       case _ =>
     }
    }

    if (value.isInstanceOf[Iterable[_]]) throw new java.lang.IllegalArgumentException("not supported data type")
    if (value.isInstanceOf[Array[_]]) throw new java.lang.IllegalArgumentException("not supported data type")
    if (value.isInstanceOf[java.util.List[_]]) throw new java.lang.IllegalArgumentException("not supported data type")
    if (value.isInstanceOf[java.util.Map[_, _]]) throw new java.lang.IllegalArgumentException("not supported data type")

    if (key.toString.isEmpty) throw Property.Exceptions.propertyKeyCanNotBeEmpty()
    if (Graph.Hidden.isHidden(key.toString)) throw Property.Exceptions.propertyKeyCanNotBeAHiddenKey(Graph.Hidden.hide(key.toString))

  }
}

case class S2Property[V](element: S2Edge,
                         labelMeta: LabelMeta,
                         key: String,
                         v: V,
                         ts: Long) extends Property[V] {

  import CanInnerValLike._
  lazy val innerVal = anyToInnerValLike.toInnerVal(value)(element.innerLabel.schemaVersion)
  lazy val innerValWithTs = InnerValLikeWithTs(innerVal, ts)

  val value = castValue(v, labelMeta.dataType).asInstanceOf[V]

  def bytes: Array[Byte] = {
    innerVal.bytes
  }

  def bytesWithTs: Array[Byte] = {
    innerValWithTs.bytes
  }

  @volatile var isRemoved = false

  override def isPresent: Boolean = !isRemoved

  override def remove(): Unit = isRemoved = true

  override def hashCode(): Int = {
    MurmurHash3.stringHash(labelMeta.labelId + "," + labelMeta.id + "," + key + "," + value + "," + ts)
  }

  override def equals(other: Any): Boolean = other match {
    case p: Property[_] =>
      key == p.key() && v == p.value()
    case _ => false
  }

  override def toString(): String = {
//    Map("labelMeta" -> labelMeta.toString, "key" -> key, "value" -> value, "ts" -> ts).toString
    // vp[name->marko]
    s"p[${key}->${value}]"
  }

}
