package com.oracle.ucm.nativews;


import com.oracle.ucm.utils.data.FileAttributes;
import com.oracle.ucm.utils.response.searchResponse;
import com.oracle.ucm.utils.response.fileResponse;
import com.oracle.ucm.utils.response.docInfoResponse;

import java.io.InputStream;


import oracle.stellent.ridc.IdcClientManager;
import oracle.stellent.ridc.IdcClientException;
import oracle.stellent.ridc.model.DataBinder;
import oracle.stellent.ridc.protocol.jaxws.JaxWSClient;
import oracle.stellent.ridc.protocol.jaxws.JaxWSClientConfig;


import java.util.HashMap;

import java.util.Iterator;
import java.util.Set;

import oracle.stellent.ridc.IdcContext;
import oracle.stellent.ridc.model.TransferFile;
import oracle.stellent.ridc.protocol.ServiceResponse;
import oracle.stellent.ridc.model.DataResultSet.Field;

import com.oracle.ucm.utils.response.ucmResponse;
import com.oracle.ucm.utils.data.docInfoContainer;

import com.oracle.ucm.utils.data.resultsContainer;

import java.util.List;

import oracle.stellent.ridc.IdcClient;
import oracle.stellent.ridc.model.DataResultSet;
import oracle.stellent.ridc.model.impl.DataResultSetRow;


public class NativeProxy 
{
    
    private static final String PROTOCOL_RIDC = "idc";
    private static final String PROTOCOL_NATIVEWS = "nativews";
    private static final String API_RIDC = "RIDC";
    private static final String API_NATIVEWS = "NativeWS";
    private IdcClient m_wsclient = null;
    private IdcContext m_usercontext = null;
    private String m_protocoltype = null;
    private String m_userprinciple;
    
    public NativeProxy() 
    {
        super();
        m_protocoltype = PROTOCOL_RIDC;
        m_userprinciple = "weblogic";
    }
    
    public NativeProxy(String apiopt, String userid)
    {
        if (API_NATIVEWS.equals(apiopt))
            m_protocoltype = PROTOCOL_NATIVEWS;
        else
            m_protocoltype = PROTOCOL_RIDC;
        m_userprinciple = userid;
    }
    
    public void init(String protocol) throws IdcClientException
    {
        IdcClientManager manager = new IdcClientManager();
       if (API_NATIVEWS.equals(protocol)) 
       {
            m_wsclient =
                    (JaxWSClient)manager.createClient("http://slc03nbl:16200/idcnativews");
            JaxWSClientConfig jaxwsConfig =
                (JaxWSClientConfig)m_wsclient.getConfig();
            //You can set the instance name of the Content Server that you would like to connect to. This is set to "/cs/" by default which is the default webcontext for UCM installation. If the server webcontext is different than the default, then you may set it as:

            //The default configuration for the service instance name is /cs/. The call to .setServerInstanceName is only needed if you have deployed the native webservices in a way that deviates from the default deployment
            //jaxwsConfig.setServerInstanceName("/cs/");

            //Setting the JPS configuration file location. A JPS configuration file is required for most policies such SAML and/or Message Token.
            jaxwsConfig.setJpsConfigFile("d:/keystore/jps-config.xml");

            //Setting the security policy:
            jaxwsConfig.setClientSecurityPolicy("oracle/wss11_saml_token_with_message_protection_client_policy");

            //The default configuration for the Request End Point is constructed by using the URL the idc client was created and appending /IdcWebRequestPort to it.
            //The call to the .setRequestServiceEndponitURL is only needed if you have deployed the native webservices in a way that deviates from the default deployment
            //jaxwsConfig.setRequestServiceEndpointUrl("http://localhost:16200/idcnativews/IdcWebRequestPort");

            //The default configuration for the Login WSDL End Point is constructed by using the URL the idc client was created and appending /IdcWebLoginPort?wsdl to it.
            //The call to the .setLoginServiceWSDLUrl is only needed if you have deployed the native webservices in a way that deviates from the default deployment
            //jaxwsConfig.setLoginServiceWSDLUrl("http://localhost16200/idcnativews/IdcWebLoginPort?wsdl");

            //The default configuration for the Request WSDL End Point is constructed by using the URL the idc client was created and appending /IdcWebRequestPort?WSDL to it.
            //The call to the .setLoginServiceWSDLUrl is only needed if you have deployed the native webservices in a way that deviates from the default deployment
            //jaxwsConfig.setRequestServiceWSDLUrl("http://slc03nbl.us.oracle.com:16200/idcnativews/IdcWebRequestPort?wsdl");

            //The default streaming chuck size is 8192. This example changes the chunk size:
            jaxwsConfig.setStreamingChunkSize(8192);

            //Note a user context is required to pass to client sendRequest method, however when using SAML Cert to propagate identity this conext is not used by the server
            //The identiry from the SAML cert is used
            m_usercontext = new IdcContext("sysadmin", "idc");
        } 
       else 
       {
            m_wsclient =
                    manager.createClient("idc://slc03nbl.us.oracle.com:4444");
            m_usercontext = new IdcContext(m_userprinciple);

        }


    }
    
    public ucmResponse executeCheckInService(HashMap metafields, String fName, String contentType, InputStream is) 
    {
        
        try
        {
            init(m_protocoltype);
            DataBinder binder = m_wsclient.createBinder();
        
            binder.putLocal("IdcService", "CHECKIN_NEW");
            Set fldset = metafields.keySet();
            Iterator fldnames = fldset.iterator();
            //build up list of fields for metadata on checkin
            while (fldnames.hasNext()) 
            {
                String fldname = (String)fldnames.next();
                String val = (String)metafields.get(fldname);
                binder.putLocal(fldname, val);
            }
            
            TransferFile tf = new TransferFile();
            tf.setInputStream(is);
            tf.setFileName(fName);
            tf.setContentType(contentType);
            binder.addFile("primaryFile", tf);
           
            ServiceResponse svcrsp = m_wsclient.sendRequest(m_usercontext, binder);
            ucmResponse rsp = new ucmResponse(svcrsp.getResponseAsBinder());
            return rsp;
        }
        
        catch (IdcClientException idce) 
        {
            DataBinder errbnd = m_wsclient.createBinder();
            errbnd.putLocal("StatusCode", "-1");
            errbnd.putLocal("StatusMessage", idce.getMessage());
            ucmResponse errrsp = new ucmResponse(errbnd);
            return errrsp;
        }
        
    }
    
    public docInfoResponse executeDocInfo(String docname, String did)
    {
        docInfoResponse dir = null;        
        try
        {
            init(m_protocoltype);
            DataBinder binder = m_wsclient.createBinder();
            
            binder.putLocal("IdcService", "DOC_INFO");
            binder.putLocal("dID", did);
            if (docname != null)
                binder.putLocal("dDocName", docname);
            docInfoContainer dinfocont = new docInfoContainer();
            ServiceResponse svcrsp = m_wsclient.sendRequest(m_usercontext, binder);
            DataBinder rspbinder = svcrsp.getResponseAsBinder();
            dir = new docInfoResponse(rspbinder);
            if ("0".equals(dir.getStatusCode()))
            {
                DataResultSet docinfo_rs = rspbinder.getResultSet("DOC_INFO");
                dinfocont.initDocInfo(docinfo_rs.getFields().size(), docinfo_rs.getRows().size());
                String colhdrs[] = new String[dinfocont.getDocInfoNumCols()];
                List dinfohdrs = docinfo_rs.getFields();
                int numcols = dinfohdrs.size();
                for (int colidx = 0; colidx < numcols; ++colidx)
                { 
                  Field f = (Field)dinfohdrs.get(colidx);
                  colhdrs[colidx] = f.getName();
                  
                }
                
                dinfocont.setDocInfoCols(colhdrs);
                
                // Print out the row data
                String rows[][] = new String[dinfocont.getDocInfoNumRows()][dinfocont.getDocInfoNumCols()];
                List dinforows = docinfo_rs.getRows();
                int numrows = dinforows.size();
                //traverse rows
                for (int rowidx = 0; rowidx < numrows; ++rowidx)
                { 
                    //traverse columns in current row
                    DataResultSetRow drsrow = (DataResultSetRow)dinforows.get(rowidx);
                    for (int colidx = 0; colidx < dinfocont.getDocInfoNumCols(); ++colidx) 
                    {
                        String colname = dinfocont.getDocInfoCols()[colidx];
                        rows[rowidx][colidx] = drsrow.get(colname);
                    }
                    
                }
                dinfocont.setDocInfoRows(rows);
                
                DataResultSet revhist_rs = rspbinder.getResultSet("REVISION_HISTORY");
                dinfocont.initRevHistory(revhist_rs.getFields().size(), revhist_rs.getRows().size());
                String revrows[][] = new String[dinfocont.getRevHistoryNumRows()][dinfocont.getRevHistoryNumCols()];
                List revhistrows = revhist_rs.getRows();
                int numhistrows = revhistrows.size();
                //traverse rows
                for (int rowidx = 0; rowidx < numhistrows; ++rowidx)
                { 
                    //traverse columns in current row
                    DataResultSetRow drsrow = (DataResultSetRow)revhistrows.get(rowidx);
                    Iterator rowit = drsrow.keySet().iterator();
                    int colidx = 0;
                    while (rowit.hasNext())
                    {
                        String key = (String)rowit.next();
                        revrows[rowidx][colidx] = (String)drsrow.get(key);
                        ++colidx;
                    }
                }
                dinfocont.setRevHistoryRows(revrows);
            }
            dir.setResults(dinfocont);
        }//try
        
        catch (IdcClientException idce) 
        {
            DataBinder errbinder = m_wsclient.createBinder();
            errbinder.putLocal("StatusCode", "-1");
            errbinder.putLocal("StatusMessage", idce.getMessage());
            dir = new docInfoResponse(errbinder);
        }
        return dir;
    }
    
    public searchResponse executeSearch(String ftxcriteria)
    {
        searchResponse sr = null;
        try 
        {
            init(m_protocoltype);
            DataBinder reqbinder = m_wsclient.createBinder();
            reqbinder.putLocal("IdcService", "GET_SEARCH_RESULTS");
            if (ftxcriteria.length() > 0)
            {
                reqbinder.putLocal("QueryText",
                                   "<ftx>" + ftxcriteria + "</ftx>");
                reqbinder.putLocal("ftx", "1");
            } 
            else
            {
                reqbinder.putLocal("QueryText", "");
            }


            reqbinder.putLocal("SortField", "dInDate");
            reqbinder.putLocal("SortOrder", "Desc");
            reqbinder.putLocal("ResultCount", "200");
            resultsContainer rsc = new resultsContainer();
            //execute search request to server that returns response as a Service ojbect
            ServiceResponse svcrsp = m_wsclient.sendRequest(m_usercontext, reqbinder);
            DataBinder rspbinder = svcrsp.getResponseAsBinder();
            sr = new searchResponse(rspbinder);
            if ("0".equals(sr.getStatusCode())) 
            {
                DataResultSet searchResults = rspbinder.getResultSet("SearchResults");

                if (searchResults.getRows().size() > 0) 
                {
                    rsc.init(searchResults.getFields().size(),
                             searchResults.getRows().size());
                    String colhdrs[] = new String[rsc.getNumCols()];
                    List srchhdrs = searchResults.getFields();
                    for (int colidx = 0; colidx < srchhdrs.size(); ++colidx) 
                    {
                        Field f = (Field)srchhdrs.get(colidx);
                        colhdrs[colidx] = f.getName();

                    }
                    rsc.setCols(colhdrs);
                }

                // Print out the row data
                String rows[][] = new String[rsc.getNumRows()][rsc.getNumCols()];
                List srchrows = searchResults.getRows();
                for (int rowidx = 0; rowidx < srchrows.size(); ++rowidx)
                {
                    //traverse columns in current row
                    DataResultSetRow drsrow = (DataResultSetRow)srchrows.get(rowidx);
                    for (int colidx = 0; colidx < rsc.getNumCols(); ++colidx) 
                    {
                        String curcol = rsc.getCols()[colidx];
                        rows[rowidx][colidx] = drsrow.get(curcol);
                    }

                }
                rsc.setRows(rows);
                sr.setResults(rsc);
            }
        }

        catch (IdcClientException idce) 
        {
            DataBinder errbinder = m_wsclient.createBinder();
            errbinder.putLocal("StatusCode", "-1");
            errbinder.putLocal("StatusMessage", idce.getMessage());
            sr = new searchResponse(errbinder);
        }

        return sr;
        
        
    }
    
    public ucmResponse executeDeleteRev(String dDocName, String dID)
    {
        ucmResponse rsp = null;
        try
        {    
            init(m_protocoltype);
            DataBinder reqbinder = m_wsclient.createBinder();
            reqbinder.putLocal("IdcService", "DELETE_REV");
            reqbinder.putLocal("dDocName", dDocName);
            reqbinder.putLocal("dID", dID);
            ServiceResponse svcrsp = m_wsclient.sendRequest(m_usercontext, reqbinder);
            DataBinder rspbinder = svcrsp.getResponseAsBinder();
            rsp = new ucmResponse(rspbinder);
            if ("-64".equals(rsp.getStatusCode())) 
            {
                //ucm server returns an error code 0f -64 when the final revision of a document is deleted this is not an error
                //set status code to zero so normal response is rendered
                rsp.setStatusCode("0");
            }
        }
        
        catch (IdcClientException idce) 
        {
            DataBinder errbinder = m_wsclient.createBinder();
            if (idce.getMessage().indexOf("has been successfully deleted") != -1) 
            {
                //ridc interface throws a client exception when the final revision of a content item is deleted
                //which is not an error overriding this so that standard error message can be rendered
                errbinder.putLocal("StatusCode", "0"); 
            }
            else
            {
                errbinder.putLocal("StatusCode", "-1");
                errbinder.putLocal("StatusMessage", idce.getMessage());
            }
            rsp = new ucmResponse(errbinder);
            
        }
        
        return rsp;
    }
    
    public fileResponse executeGetFile(String dID)
    {
        fileResponse fr = null;
        try
        {
            init(m_protocoltype);
            DataBinder reqbinder = m_wsclient.createBinder();
            reqbinder.putLocal("IdcService", "GET_FILE");
            reqbinder.putLocal("dID", dID);
            InputStream retis = null;
            ServiceResponse svcrsp = m_wsclient.sendRequest(m_usercontext, reqbinder);
            DataBinder rspbinder = m_wsclient.createBinder();
            rspbinder.putLocal("StatusCode", "0");
            rspbinder.putLocal("StatusMessage", "Success");
            fr = new fileResponse(rspbinder);
            retis = svcrsp.getResponseStream();
            fr.setInputStream(retis);
            
        }
        
        catch (IdcClientException idce) 
        {
            DataBinder rspbinder = m_wsclient.createBinder();
            rspbinder.putLocal("StatusCode", "-1");
            rspbinder.putLocal("StatusMessage", idce.getMessage());
            fr = new fileResponse(rspbinder);
        }
        return fr;  
    }
    
    public FileAttributes getFileAttributes(String dID) 
    {
        FileAttributes fattrib = null;
        int nameidx = 0;
        int formatidx = 0;
        int sizeidx = 0;
        
        docInfoResponse dir = executeDocInfo(null, dID);
        if ("0".equals(dir.getStatusCode()))
        {
            fattrib = new FileAttributes();
            docInfoContainer di = dir.getResults();
            for (int curcol = 0; curcol < di.getDocInfoNumCols(); ++curcol)
            {
                if ("dFormat".equals(di.getDocInfoCols()[curcol]))
                    formatidx = curcol;
                
                if ("dOriginalName".equals(di.getDocInfoCols()[curcol]))
                    nameidx = curcol;
                
                if ("dFileSize".equals(di.getDocInfoCols()[curcol]))
                    sizeidx = curcol;
            }
            
            fattrib.setFformat(di.getDocInfoRows()[0][formatidx]);
            fattrib.setFname(di.getDocInfoRows()[0][nameidx]);
            fattrib.setFsize(Integer.parseInt(di.getDocInfoRows()[0][sizeidx]));  
        }
        return fattrib;
    }
}