package in.cdac.medinfo.csnotk.csnoserv.rest;




import java.util.Set;
import static  in.cdac.medinfo.csnotk.csnoserv.CSnoServResource.*;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import in.cdac.medinfo.csnotk.csnolib.commons.EnumDirection;
import in.cdac.medinfo.csnotk.csnolib.commons.EnumLangRefset;
import in.cdac.medinfo.csnotk.csnolib.model.Concept;

//Logs
import in.cdac.medinfo.csnotk.csnolib.util.LoggerUtility;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;


@Path("/lookup")
public class LookupController{

    /**
     * Gets the Concept details for a given concept id. Descriptions and
     * relationships related to that concept are also listed.
     *
     * @param id       {@link String} concept id for which lookup is to be done
     * @param callback {@link String} name of the callback function in a jsonp
     *                 request</br>
     *                 (for allowing cross domain request)
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON + ";charset=utf-8" })
    @Path("/concept")
    public Response getConcept(@QueryParam("id") String id, @QueryParam("langrefset") String langRefset,
                               @QueryParam("callback") String callback) {

        initProperties();
        Logger logger = LogManager.getLogger(LookupController.class);

        if (id == null || id.equalsIgnoreCase("") || !id.matches(_0_9)) {
            logger.error(LoggerUtility.Exception, INVALID_QUERY_PARAMETER_VALUE_ID , id);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }

        String jsonString;
        try {
            EnumLangRefset enumLangRefset;
            if (langRefset == null || langRefset.equalsIgnoreCase("")
                    || langRefset.equalsIgnoreCase(EnumLangRefset.ALL.getValue())) {
                enumLangRefset = EnumLangRefset.ALL;
            } else {
                langRefset = java.net.URLDecoder.decode(langRefset, UTF_8);
                enumLangRefset = EnumLangRefset.getEnum(langRefset);
                if (enumLangRefset == null) {
                    logger.error(LoggerUtility.Exception, "Invalid Query Parameter Value: LangRefset: {}" , langRefset);
                    return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
                }
            }

            jsonString = gson.toJson(agent.getConceptDetails(id, enumLangRefset));

            if (null == jsonString || jsonString.equals("null")) {
                logger.error(LoggerUtility.Exception, "\nInvalid Concept ID : {}", id);
                jsonString = "[]";
                return CORSHeaderSupport.addCORSHeader(Response.Status.OK,jsonString);

            }
        } catch (Exception e) // caches any of the service exceptions
        {
            // Log the Exception
            logger.error(LoggerUtility.Exception, LoggerUtility.createErrorMessage(e));

            return CORSHeaderSupport.addCORSHeader(Response.Status.INTERNAL_SERVER_ERROR,
                    Response.Status.INTERNAL_SERVER_ERROR.toString() + " : " + LoggerUtility.createErrorMessage(e));
        }
        // if callback in URL and is not just the "?" (e.g. from localhost)
        if (callback != null && callback.length() > 1) {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,callback + "(" + jsonString + ");");
        } else {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,jsonString);
        }

    }

    /**
     * Gets all related Concept IDs for a given concept based on the relationship
     *
     * @param id        {@link String} concept id for which lookup is to be done
     * @param relation  relationship defined in SNOED CT.
     * @param direction
     * @param callback  {@link String} name of the callback function in a jsonp
     *                  request</br>
     *                  (for allowing cross domain request)
     * @return {@link Response}
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON + ";charset=utf-8" })
    @Path("/relationship")
    public Response getRelationship(@QueryParam("id") String id, @QueryParam("relation") String relation,
                                    @QueryParam("direction") String direction, @QueryParam("callback") String callback) {

        initProperties();
        Logger logger = LogManager.getLogger(LookupController.class);

        if (id.equalsIgnoreCase("null") || id.equalsIgnoreCase("") || !id.matches(_0_9)) {
            logger.error(LoggerUtility.Exception, INVALID_QUERY_PARAMETER_VALUE_ID , id);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }
        if (direction.equalsIgnoreCase("null") || direction.trim().equalsIgnoreCase("")
                || (!direction.equalsIgnoreCase("source") && !direction.equalsIgnoreCase("destination"))) {
            logger.error(LoggerUtility.Exception, "Invalid Query Parameter Value: direction: {}" , direction);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }
        if (relation.equalsIgnoreCase("null") || relation.equalsIgnoreCase("")) {
            logger.error(LoggerUtility.Exception, "Invalid Query Parameter Value: relation: {}" , relation);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }
        String jsonString;
        try {
            Concept objConcept = agent.search(id.trim());
            if (objConcept == null) {
                return CORSHeaderSupport.addCORSHeader(Response.Status.NOT_FOUND,Response.Status.NOT_FOUND.toString());
            }

            Set<Concept> relConcepts  = agent.getRelations(id, relation,EnumDirection.getEnum(direction.toLowerCase().trim()));
            jsonString = gson.toJson(relConcepts);
        } catch (Exception e) // caches any of the service exceptions
        {
            // Log the Exception
            logger.error(LoggerUtility.Exception, LoggerUtility.createErrorMessage(e));

            return CORSHeaderSupport.addCORSHeader(Response.Status.INTERNAL_SERVER_ERROR,Response.Status.INTERNAL_SERVER_ERROR.toString() + " : " + LoggerUtility.createErrorMessage(e));
        }
        // if callback in URL and is not just the "?" (e.g. from localhost)
        if (callback != null && callback.length() > 1) {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,callback + "(" + jsonString + ");");
        } else {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,jsonString);
        }

    }





}