package com.hp.autonomy.frontend.find.view;

/*
 * $Id: $
 *
 * Copyright (c) 2015, Autonomy Systems Ltd.
 *
 * Last modified by $Author: $ on $Date: $
 */

import com.hp.autonomy.frontend.find.ApiKeyService;
import com.hp.autonomy.iod.client.api.formatconversion.ViewDocumentService;
import com.hp.autonomy.iod.client.api.search.Document;
import com.hp.autonomy.iod.client.api.search.Documents;
import com.hp.autonomy.iod.client.api.search.GetContentRequestBuilder;
import com.hp.autonomy.iod.client.api.search.GetContentService;
import com.hp.autonomy.iod.client.api.search.Print;
import com.hp.autonomy.iod.client.error.IodErrorCode;
import com.hp.autonomy.iod.client.error.IodErrorException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.validator.routines.UrlValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import retrofit.client.Response;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class IodViewServiceImpl implements IodViewService {

    @Autowired
    private ApiKeyService apiKeyService;

    @Autowired
    private GetContentService getContentService;

    @Autowired
    private ViewDocumentService viewDocumentService;

    @Override
    public void viewDocument(final OutputStream outputStream, final String documentReference, final String indexes) throws IOException, IodErrorException {
        // call get content with document reference
        // if no document will throw IodErrorException
        // if document has a url, view it
        // if document has object store reference, view it
        // else show the text content
        final Map<String, Object> getContentParams = new GetContentRequestBuilder()
                .setPrint(Print.all)
                .build();

        final Documents documents = getContentService.getContent(apiKeyService.getApiKey(), Collections.singletonList(documentReference), indexes, getContentParams);
        final Document document = documents.getDocuments().get(0);

        final Map<String, Object> fields = document.getFields();
        final Object urlField = fields.get("url");

        final String documentUrl;

        if(urlField instanceof List) {
            documentUrl = ((List<?>) urlField).get(0).toString();
        }
        else {
            documentUrl = document.getReference();
        }

        final UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES);

        InputStream inputStream;

        try {
            final URL url = new URL(documentUrl);
            final URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), url.getQuery(), null);
            final String encodedUrl = uri.toASCIIString();

            if (urlValidator.isValid(encodedUrl)) {
                final Response response = viewDocumentService.viewUrl(encodedUrl, null);
                inputStream = response.getBody().in();
            } else {
                throw new URISyntaxException(encodedUrl, "Invalid URL");
            }
        } catch (final URISyntaxException | MalformedURLException | IodErrorException e) {
            // url was not valid or IOD failed, use content instead
            inputStream = IOUtils.toInputStream(document.getContent(), "UTF-8");
        }

        IOUtils.copy(inputStream, outputStream);

        inputStream.close();
    }
}

@@ -1477,35 +1477,44 @@
     
-@Override%0A    public void v
+/**%0A     * Uses IOD GetContent and V
 iewD
@@ -1524,168 +1524,218 @@
 ment
-(final OutputStream outputStream, final String documentReference, final String indexes) throws IOException, IodErrorException %7B%0A        // call get content wi
+ to return the content of a document.%0A     * @param outputStream  Stream to write the document to%0A     * @param documentReference  Document reference to load%0A     * @param indexes  IOD Indexes to search for 
 th
+e
  doc
@@ -1753,45 +1753,53 @@
 ence
+ in
 %0A     
-   // if no document will 
+* @throws IOException%0A     * @
 throw
+s
  Iod
@@ -1812,27 +1812,24 @@
 xception
-%0A
   
-      //
+Thrown
  if docu
@@ -1837,123 +1837,349 @@
 ent 
-has a url, view it%0A        // if document has object store reference, view it%0A        // else show the text content
+reference is invalid/not found in the indexes supplied%0A     */%0A    @Override%0A    public void viewDocument(final OutputStream outputStream, final String documentReference, final String indexes) throws IOException, IodErrorException %7B%0A%0A        // Call GetContent with the document reference as we need details from the full document (e.g. URL)
 %0A   
@@ -2319,24 +2319,104 @@
  .build();%0A%0A
+        // An IodErrorException can be thrown here if the document isn't found.%0A
         fina
@@ -2633,24 +2633,73 @@
 ().get(0);%0A%0A
+        // Check for a URL field on the document%0A
         fina
@@ -2802,17 +2802,16 @@
 %22url%22);%0A
-%0A
         
@@ -2959,32 +2959,133 @@
 %0A        else %7B%0A
+            // If there isn't a URL field, use the document reference - this is often actually a URL%0A
             docu
@@ -3217,24 +3217,59 @@
 _SLASHES);%0A%0A
+        // Attempt to load the URL%0A
         Inpu
@@ -3289,17 +3289,16 @@
 Stream;%0A
-%0A
         
@@ -3936,19 +3936,30 @@
      // 
-url
+Fallback - URL
  was not
@@ -3984,23 +3984,45 @@
 ed, use 
-content
+raw document content from IOD
  instead
@@ -4163,17 +4163,16 @@
 tream);%0A
-%0A
         

Improve comments