/*
 * 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.nlpcraft.server.json

import java.io.{IOException, _}
import java.util.zip._

import com.typesafe.scalalogging.LazyLogging
import net.liftweb.json.{compactRender ⇒ liftCompact, prettyRender ⇒ liftPretty, _}
import org.apache.nlpcraft.common._

import scala.annotation.tailrec
import scala.language.implicitConversions
import scala.util.matching.Regex

/**
 * Project-wide, Lift-based general JSON wrapper.
 */
class NCJson(val json: JValue) {
    import NCJson._

    require(json != null)

    // Delegate to underlying JValue.
    override def hashCode(): Int = json.hashCode()
    override def equals(obj: scala.Any): Boolean = json.equals(obj)

    /**
     * Convenient method to get JSON unboxed value with given type and name.
     *
     * @param fn Field name.
     * @tparam T Type of the value.
     */
    @throws[NCJ]
    def field[T](fn: String): T =
        try
            json \ fn match {
                case JNothing | null ⇒ throw MissingJsonField(fn)
                case v: JValue ⇒ v.values.asInstanceOf[T]
            }
        catch {
            case e: MissingJsonField ⇒ throw e // Rethrow.
            case e: Throwable ⇒ throw InvalidJsonField(fn, e)
        }

    /**
      * Tests whether given JSON field present or not.
      *
      * @param fn JSON field name.
      */
    def hasField(fn: String): Boolean =
        json \ fn match {
            case JNothing | null ⇒ false
            case _: JValue ⇒ true
        }

    /**
     * Convenient method to get JSON unboxed value with given type and name.
     *
     * @param fn Field name.
     * @tparam T Type of the value.
     */
    def fieldOpt[T](fn: String): Option[T] =
        try
            json \ fn match {
                case JNothing ⇒ None
                case v: JValue ⇒ Some(v.values.asInstanceOf[T])
            }
        catch {
            case _: Throwable ⇒ None
        }

    /**
     * Renders this JSON with proper new-lines and indentation (suitable for human readability).
     *
     * @return String presentation of this JSON object.
     */
    def pretty: String = liftPretty(json)

    /**
     * Renders this JSON in a compact form (suitable for exchange).
     *
     * @return String presentation of this JSON object.
     */
    def compact: String = liftCompact(json)

    /**
     * Zips this JSON object into array of bytes using GZIP.
     */
    def gzip(): Array[Byte] = {
        val out = new ByteArrayOutputStream(1024)

        try {
            val gzip = new GZIPOutputStream(out)

            gzip.write(compact.getBytes)

            gzip.close()

            out.toByteArray
        }
        // Let IOException to propagate unchecked (since it shouldn't appear here by the spec).
        finally {
            out.close()
        }
    }

    override def toString: String = compact
}

/**
 * Static scope for JSON wrapper.
 */
object NCJson {
    private type NCJ = NCJsonException

    // Specific control flow exceptions.
    case class InvalidJson(js: String) extends NCJ(s"Malformed JSON syntax: $js") with LazyLogging {
        // Log right away.
        logger.error(s"Malformed JSON syntax: $js")
    }

    case class InvalidJsonField(fn: String, cause: Throwable) extends NCJ(s"Invalid '$fn' JSON field <" +
        cause.getMessage + ">", cause) with LazyLogging {
        require(cause != null)

        // Log right away.
        logger.error(s"Invalid '$fn' JSON field <${cause.getMessage}>")
    }

    case class MissingJsonField(fn: String) extends NCJ(s"Missing mandatory '$fn' JSON field.") with LazyLogging {
        // Log right away.
        logger.error(s"Missing mandatory '$fn' JSON field.")
    }

    implicit val formats: DefaultFormats.type = net.liftweb.json.DefaultFormats

    // Regex for numbers with positive exponent part with explicit + in notation. Example 2E+5.
    // Also, these numbers should be pre-fixed and post-fixed by restricted JSON symbols set.
    private val EXP_REGEX = {
        val mask = "[-+]?([0-9]+\\.?[0-9]*|\\.[0-9]+)([eE]\\+[0-9]+)"
        val pre = Seq(' ', '"', '[', ',', ':')
        val post = Seq(' ', '"', ']', ',', '}')

        def makeMask(chars: Seq[Char]): String = s"[${chars.map(ch ⇒ s"\\$ch").mkString}]"

        new Regex(s"${makeMask(pre)}$mask${makeMask(post)}")
    }

    /**
     * Creates JSON wrapper from given string.
     *
     * @param js JSON string presentation.
     * @return JSON wrapper.
     */
    @throws[NCJ]
    def apply(js: String): NCJson = {
        require(js != null)

        JsonParser.parseOpt(processExpNumbers(js)) match {
            case Some(a) ⇒ new NCJson(a)
            case _ ⇒ throw InvalidJson(js)
        }
    }

    /**
     * Creates JSON wrapper from given Lift `JValue` object.
     *
     * @param json Lift `JValue` AST object.
     * @return JSON wrapper.
     */
    @throws[NCJ]
    def apply(json: JValue): NCJson = {
        require(json != null)

        new NCJson(json)
    }


    /**
     * Unzips array of bytes into string.
     *
     * @param arr Array of bytes produced by 'gzip' method.
     */
    def unzip2String(arr: Array[Byte]): String = {
        val in = new ByteArrayInputStream(arr)
        val out = new ByteArrayOutputStream(1024)

        val tmpArr = new Array[Byte](512)

        try {
            val gzip = new GZIPInputStream(in)

            var n = gzip.read(tmpArr, 0, tmpArr.length)

            while (n > 0) {
                out.write(tmpArr, 0, n)

                n = gzip.read(tmpArr, 0, tmpArr.length)
            }

            gzip.close()

            // Trim method added to delete last symbol of ZLIB compression
            // protocol (NULL - 'no error' flag) http://www.zlib.net/manual.html
            out.toString("UTF-8").trim
        }
        // Let IOException to propagate unchecked (since it shouldn't appear here by the spec).
        finally {
            out.close()
            in.close()
        }
    }

    /**
     * Unzips array of bytes into JSON object.
     *
     * @param arr Array of bytes produced by 'gzip' method.
     */
    def unzip2Json(arr: Array[Byte]): NCJson = NCJson(unzip2String(arr))

    /**
     * Reads file.
     *
     * @param f File to extract from.
     */
    private def readFile(f: File): String = removeComments(U.readFile(f).mkString)

    /**
      * Reads stream.
      *
      * @param in Stream to extract from.
      */
    private def readStream(in: InputStream): String = removeComments(U.readStream(in).mkString)

    /**
     * Extracts type `T` from given JSON `file`.
     *
     * @param f File to extract from.
     * @param ignoreCase Whether or not to ignore case.
     * @tparam T Type of the object to extract.
     */
    @throws[NCE]
    def extractFile[T: Manifest](f: java.io.File, ignoreCase: Boolean): T =
        try
            if (ignoreCase) NCJson(readFile(f).toLowerCase).json.extract[T] else NCJson(readFile(f)).json.extract[T]
        catch {
            case e: IOException ⇒ throw new NCE(s"Failed to read: ${f.getAbsolutePath}", e)
            case e: Throwable ⇒ throw new NCE(s"Failed to parse: ${f.getAbsolutePath}", e)
        }

    /**
     * Removes C-style /* */ multi-line comments from JSON.
     *
     * @param json JSON text.
     */
    private def removeComments(json: String): String = json.replaceAll("""/\*(\*(?!/)|[^*])*\*/""", "")

    /**
     * Extracts type `T` from given JSON `file`.
     *
     * @param path File path to extract from.
     * @param ignoreCase Whether or not to ignore case.
     * @tparam T Type of the object to extract.
     */
    @throws[NCE]
    def extractPath[T: Manifest](path: String, ignoreCase: Boolean): T = extractFile(new java.io.File(path), ignoreCase)

    /**
      * Extracts type `T` from given JSON `file`.
      *
      * @param res Resource to extract from.
      * @param ignoreCase Whether or not to ignore case.
      * @tparam T Type of the object to extract.
      */
    @throws[NCE]
    def extractResource[T: Manifest](res: String, ignoreCase: Boolean): T =
        try {
            val in = U.getStream(res)

            if (ignoreCase) NCJson(readStream(in).toLowerCase).json.extract[T] else NCJson(readStream(in)).json.extract[T]
        }
        catch {
            case e: IOException ⇒ throw new NCE(s"Failed to read: $res", e)
            case e: Throwable ⇒ throw new NCE(s"Failed to parse: $res", e)
        }

    // Gets string with removed symbol + from exponent part of numbers.
    // It is developed to avoid Lift parsing errors during processing numbers like '2E+2'.
    @tailrec
    def processExpNumbers(s: String): String =
        EXP_REGEX.findFirstMatchIn(s) match {
            case Some(m) ⇒ processExpNumbers(m.before + m.group(0).replaceAll("\\+", "") + m.after)
            case None ⇒ s
        }

    // Implicit conversions.
    implicit def x(jv: JValue): NCJson = new NCJson(jv)
    implicit def x1(js: NCJson): JValue = js.json
    implicit def x2(likeJs: NCJsonLike): JValue = likeJs.toJson.json
    implicit def x3(likeJs: NCJsonLike): NCJson = likeJs.toJson
    implicit def x4(js: NCJson): String = js.compact
    implicit def x4(js: NCJsonLike): String = js.toJson.compact
}
