/*
 * 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.model.intent.solver

import com.typesafe.scalalogging.LazyLogging
import io.opencensus.trace.Span
import org.apache.nlpcraft.common._
import org.apache.nlpcraft.common.debug.NCLogHolder
import org.apache.nlpcraft.common.opencensus.NCOpenCensusTrace
import org.apache.nlpcraft.common.util.NCUtils
import org.apache.nlpcraft.model.impl.NCVariantImpl
import org.apache.nlpcraft.model.intent.NCIdlIntent
import org.apache.nlpcraft.model.{NCContext, NCIntentMatch, NCIntentSkip, NCModel, NCRejection, NCResult, NCToken, NCVariant}
import org.apache.nlpcraft.probe.mgrs.dialogflow.NCDialogFlowManager

import scala.collection.JavaConverters._

/**
 * Front-end for intent solver.
 */
class NCIntentSolver(intents: List[(NCIdlIntent/*Intent*/, NCIntentMatch ⇒ NCResult/*Callback*/)])
    extends LazyLogging with NCOpenCensusTrace {
    class RedoSolver extends RuntimeException

    /**
     *
     * @param in
     * @param span
     * @return
     */
    def solve(in: NCIntentSolverInput, span: Span): NCResult = {
        var doIt = true
        var res: NCResult = null
        
        while (doIt)
            try {
                res = solve0(in, span)
                
                doIt = false
            }
            catch {
                case _: RedoSolver ⇒ ()
            }
        
        res
    }
    
    /**
     *
     * @param in Intent solver input.
     * @param span Parent span.
     * @return
     * @throws NCRejection
     */
    def solve0(in: NCIntentSolverInput, span: Span): NCResult = {
        if (intents.isEmpty)
            // Should it be an assertion?
            throw new NCRejection("Intent solver has no registered intents.")
        
        val ctx = in.context
        
        val req = ctx.getRequest
        val meta = ctx.getModel.getMetadata
        
        val logHldr = meta synchronized {
            meta.get(NCUtils.mkLogHolderKey(req.getServerRequestId)).asInstanceOf[NCLogHolder]
        }
    
        val results = try NCIntentSolverEngine.solve(ctx, intents, logHldr) catch {
            case e: Exception ⇒ throw new NCRejection("Processing failed due to unexpected error.", e)
        }
        
        if (results.isEmpty)
            throw new NCRejection("No matching intent found.")

        var i = -1
    
        for (res ← results if res != null) {
            try {
                i += 1
                
                val intentMatch: NCIntentMatch = new NCIntentMatch() {
                    override val getContext: NCContext =
                        ctx
                    override val getIntentTokens: java.util.List[java.util.List[NCToken]] =
                        res.groups.map(_.tokens.asJava).asJava
                    override val getVariant: NCVariant =
                        new NCVariantImpl(res.variant.tokens)
                    override val isAmbiguous: Boolean =
                        !res.isExactMatch
                    override val getIntentId: String =
                        res.intentId
                    override def getTermTokens(idx: Int): java.util.List[NCToken] =
                        res.groups(idx).tokens.asJava
                    override def getTermTokens(termId: String): java.util.List[NCToken] =
                        res.groups.find(_.termId === termId).flatMap(grp ⇒ Some(grp.tokens)).getOrElse(Nil).asJava
                }
                
                if (!in.context.getModel.asInstanceOf[NCModel].onMatchedIntent(intentMatch)) {
                    logger.info(
                        s"Model '${ctx.getModel.getId}' triggered rematching of intents " +
                        s"by intent '${res.intentId}' on variant #${res.variantIdx + 1}."
                    )
                    
                    throw new RedoSolver
                }
                
                var cbRes: NCResult = null
    
                startScopedSpan("intentCallback", span) { _ ⇒
                    cbRes = res.fn.apply(intentMatch)
                }
                
                // Store winning intent match in the input.
                in.intentMatch = intentMatch
                
                // Don't override if user already set it.
                if (cbRes.getTokens == null)
                    cbRes.setTokens(res.groups.flatMap(_.tokens).asJava)

                if (cbRes.getIntentId == null)
                    cbRes.setIntentId(res.intentId)
                    
                logger.info(s"Intent '${res.intentId}' for variant #${res.variantIdx + 1} selected as the ${g(bo("'best match'"))}.")

                NCDialogFlowManager.addMatchedIntent(
                    intentMatch,
                    res,
                    ctx,
                    span
                )
                
                if (logHldr != null)
                    logHldr.setMatchedIntentIndex(i)
                    
                return cbRes
            }
            catch {
                case e: NCIntentSkip ⇒
                    // No-op - just skipping this result.
                    e.getMessage match {
                        case s if s != null ⇒ logger.info(s"Selected intent '${res.intentId}' skipped: $s")
                        case _ ⇒ logger.info(s"Selected intent '${res.intentId}' skipped.")
                    }
            }
        }
        
        throw new NCRejection("No matching intent found - all intents were skipped.")
    }
}
