/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package pl.edu.pwr.nlprestservice;

import java.io.InputStream;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import pl.edu.pwr.nlptools.NLPTool;
import pl.edu.pwr.nlptools.NLPToolException;
import pl.edu.pwr.nlptools.Status;

/**
 * REST Web Service
 *
 * @author www_zsk
 */

@Singleton
@Path("base")
public class BaseResource {
    ConcurrentHashMap<String, Task> tasks;
    @Context
    private UriInfo context;

    /**
     * Creates a new instance of BaseResource
     */
    public BaseResource() {
        this.tasks = new ConcurrentHashMap<>(16, 0.9f, 1);
    }
    
    
   
     @POST
    @Path("upload")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadf(@FormParam("file") String data) 
    {    
        return upload(data);
    }       
    /*
    @POST
    @Path("upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadfm(@FormDataParam("file") String data) 
    {    
        return upload(data);
    }       
    */
    
    @POST
    @Path("upload")
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public String upload(String data) 
    { if (data==null)
          throw new WebApplicationException(createResponse(new Exception("Empty data"), Response.Status.BAD_REQUEST));
        try {
        NLPTool tool=new NLPTool();
      String id=tool.saveText(data);
      id=tool.encrypt(id);
      return id;
       }
      catch (NLPToolException ex) {
                throw new WebApplicationException(createResponse(ex, Response.Status.INTERNAL_SERVER_ERROR));
            }
    }
    
    
    @POST
    @Path("upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public String uploadBinMulti(@FormDataParam("file") InputStream data) 
    { if (data==null)
          throw new WebApplicationException(createResponse(new Exception("Empty data"), Response.Status.BAD_REQUEST));
        try {
        NLPTool tool=new NLPTool();
      String id=tool.saveBinary(data);
      
      id=tool.encrypt(id);
      return id;
       }
      catch (NLPToolException ex) {
                throw new WebApplicationException(createResponse(ex, Response.Status.INTERNAL_SERVER_ERROR));
            }
    }
    
    
    @POST
    @Path("upload")
    
    //@Produces(MediaType.TEXT_PLAIN)
    public String uploadBin(byte []data) 
    { if (data==null)
          throw new WebApplicationException(createResponse(new Exception("Empty data"), Response.Status.BAD_REQUEST));
        try {
        NLPTool tool=new NLPTool();
      String id=tool.saveBinary(data);
      
      id=tool.encrypt(id);
      return id;
       }
      catch (NLPToolException ex) {
                throw new WebApplicationException(createResponse(ex, Response.Status.INTERNAL_SERVER_ERROR));
            }
    }
    
    
    @GET     
    @Path("upload/{data}")
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadGet(@PathParam("data") String data) throws NLPToolException
    { NLPTool tool=new NLPTool();
      String id=tool.saveText(data);
      id=tool.encrypt(id);
      return id;
    }
    
    
    @POST     
    @Path("uploadurl")
    @Consumes("application/json")
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadurl(String data) throws NLPToolException
    { NLPTool tool=new NLPTool();
      JSONObject jsondata= new JSONObject(data);
      String url=jsondata.getString("url");
      String id=tool.saveURL(url);
      //tool.upload2dspace(id,"11321", "7", "AA Testowy plik");
      id=tool.encrypt(id);
      return id;
    }
    
    
    @GET
    @Path("download/{fileID}")
    @Produces(MediaType.APPLICATION_XML)
    public String downlod(@PathParam("fileID") String fileID) throws NLPToolException
    { NLPTool tool=new NLPTool();
       fileID=tool.decrypt(fileID);
      return new String(tool.readFile(fileID));
    }
    
    
    @GET
    @Path("downloadbin/{fileID}")
    
    public byte[] downlodbin(@PathParam("fileID") String fileID) throws NLPToolException
    { NLPTool tool=new NLPTool();
       fileID=tool.decrypt(fileID);
      return tool.readFileBinary(fileID);
    }
    
    
     @GET
    @Path("downloadbin/{fileID}/{fileName}")
    
    public byte[] downlodbinfile(@PathParam("fileID") String fileID,@PathParam("fileName") String fileName) throws NLPToolException
    { NLPTool tool=new NLPTool();
       fileID=tool.decrypt(fileID);
      return tool.readFileBinary(fileID+"/"+fileName);
    }
    
    @GET
    @Path("startTask/{serviceName}/{fileID}")
    @Produces(MediaType.TEXT_PLAIN)
    public String startTask(@PathParam("serviceName") String serviceName, @PathParam("fileID") String fileID) throws NLPToolException
    { return startTaskO(serviceName,fileID,"");
    }
    
    @GET
    @Path("startTask/{serviceName}/{fileID}/{options}")
    @Produces(MediaType.TEXT_PLAIN)
    public String startTaskO(@PathParam("serviceName") String serviceName, @PathParam("fileID") String fileID,@PathParam("options") String options) throws NLPToolException
    {  NLPTool tool=new NLPTool(serviceName);
       fileID=tool.decrypt(fileID);
       String taskID=tool.startTask(fileID,options);
       taskID=tool.encrypt(taskID);
       return taskID;
    }
    
      
    @GET
    @Path("process/{serviceName}/{fileID}/{options}")
    @Produces(MediaType.TEXT_PLAIN)
    public String processFile(@PathParam("serviceName") String serviceName, @PathParam("fileID") String fileID,@PathParam("options") String options) throws NLPToolException
    {  NLPTool tool=new NLPTool(serviceName);
       fileID=tool.decrypt(fileID);
       String taskID=tool.processFile(fileID,options);
       taskID=tool.encrypt(taskID);
       return taskID;
    }
    
    @GET
    @Path("process/{serviceName}/{fileID}")
    @Produces(MediaType.TEXT_PLAIN)
    public String processFile(@PathParam("serviceName") String serviceName, @PathParam("fileID") String fileID) throws NLPToolException
    {
      return processFile(serviceName,fileID,"");
    }
    
    
    /**
     *
     * @param data
     * @return
     * @throws pl.edu.pwr.nlptools.NLPToolException
     */
    @POST
    @Path("zipFiles/")
    @Consumes("application/json")
    @Produces(MediaType.TEXT_PLAIN)
    public String zipFiles(String data) throws NLPToolException
    {  JSONArray fileList; JSONArray nameList;
        try {
        JSONObject jsondata= new JSONObject(data);
        fileList = jsondata.getJSONArray("id");
        nameList = jsondata.getJSONArray("name");
        } 
       catch (JSONException e)
       {
         throw new  NLPToolException(e.getMessage());  
       }
       NLPTool tool=new NLPTool();
       String fileIDs[]=new String[fileList.length()];
       String  fileNames[]=new String[nameList.length()];
       for  (int i=0;i<fileList.length();i++)
       {   fileIDs[i]=tool.decrypt(fileList.getString(i));
           fileNames[i]=nameList.getString(i);
       }
       String resultID=tool.zipFiles(fileIDs, fileNames);
       resultID=tool.encrypt(resultID);
       return resultID;
    }
    
    /**
     *
     * @param data
     * @return
     * @throws pl.edu.pwr.nlptools.NLPToolException
     */
    @POST
    @Path("dirFiles/")
    @Consumes("application/json")
    @Produces(MediaType.TEXT_PLAIN)
    public String dirFiles(String data) throws NLPToolException
    {  JSONArray fileList; JSONArray nameList;
        try {
        JSONObject jsondata= new JSONObject(data);
        fileList = jsondata.getJSONArray("id");
        nameList = jsondata.getJSONArray("name");
        } 
       catch (JSONException e)
       {
         throw new  NLPToolException(e.getMessage());  
       }
       NLPTool tool=new NLPTool();
       String fileIDs[]=new String[fileList.length()];
       String  fileNames[]=new String[nameList.length()];
       for  (int i=0;i<fileList.length();i++)
       {   fileIDs[i]=tool.decrypt(fileList.getString(i));
           fileNames[i]=nameList.getString(i);
       }
       
       String resultID=tool.dirFiles(fileIDs, fileNames);
       
       resultID=tool.encrypt(resultID);
       return resultID;
    }
    
    @GET
    @Path("startText/{serviceName}/{fileID}")
    @Produces(MediaType.TEXT_PLAIN)
    public String startText(@PathParam("serviceName") String serviceName, @PathParam("fileID") String fileID) throws NLPToolException
    { String taskID;
        if (serviceName.equals("wcrft2"))
       { taskID=startTask(serviceName,fileID);}
        else 
       {
        NLPTool tool=new NLPTool("wcrft2");
        fileID=tool.decrypt(fileID);
        taskID=tool.startTask(fileID);
        Task t=new Task(taskID,serviceName);
        taskID=t.getID();
        tasks.put(taskID, t);
        
       }
       return taskID;
    }
    
    @GET
    @Path("getStatus/{taskID}")
    public String getStatus(@PathParam("taskID") String taskID) throws NLPToolException
    {  NLPTool tool=new NLPTool();
        Status st;
        if (Task.isTaskID(taskID))
        { Task t=tasks.get(taskID);
          if (t==null) { throw  new NLPToolException("Wrong task ID: "+taskID +"  "+tasks.size());}
          st=t.checkStatus();
        }
       else
        {
       
        taskID=tool.decrypt(taskID);
        st=tool.check(taskID);
        }
        JSONObject input=new JSONObject(); 
        input.put("status", st.getStatus());
        if (st.getStatus().equals("DONE"))
          input.put("value", tool.encrypt(st.getValue()));
        else
            input.put("value", st.getValue());
            
        
       return input.toString();}
    
    private Response createResponse(Exception ex, Response.Status status) {
        String message = ex.getMessage();
        if (message == null) {
            message = "Internal error";
        }
        
        return Response.status(status).entity(message).type(MediaType.TEXT_PLAIN).build();
    }

    
}

    

