/*
 * Copyright 2017 Crown Copyright
 *
 * Licensed 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 stroom.search.solr;

import stroom.docref.DocRef;
import stroom.docstore.api.DocumentResourceHelper;
import stroom.search.solr.shared.SolrConnectionTestResponse;
import stroom.search.solr.shared.SolrIndexDoc;
import stroom.search.solr.shared.SolrIndexResource;
import stroom.util.shared.EntityServiceException;
import stroom.util.shared.ModelStringUtil;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.schema.SchemaRequest.FieldTypes;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.client.solrj.response.schema.SchemaResponse.FieldTypesResponse;

import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;

class SolrIndexResourceImpl implements SolrIndexResource {

    private final SolrIndexStore solrIndexStore;
    private final DocumentResourceHelper documentResourceHelper;

    @Inject
    SolrIndexResourceImpl(final SolrIndexStore solrIndexStore,
                          final DocumentResourceHelper documentResourceHelper) {
        this.solrIndexStore = solrIndexStore;
        this.documentResourceHelper = documentResourceHelper;
    }

    @Override
    public SolrIndexDoc fetch(final String uuid) {
        return documentResourceHelper.read(solrIndexStore, getDocRef(uuid));
    }

    @Override
    public SolrIndexDoc update(final String uuid, final SolrIndexDoc doc) {
        if (doc.getUuid() == null || !doc.getUuid().equals(uuid)) {
            throw new EntityServiceException("The document UUID must match the update UUID");
        }
        return documentResourceHelper.update(solrIndexStore, doc);
    }

    private DocRef getDocRef(final String uuid) {
        return DocRef.builder()
                .uuid(uuid)
                .type(SolrIndexDoc.DOCUMENT_TYPE)
                .build();
    }

    @Override
    public List<String> fetchSolrTypes(final SolrIndexDoc solrIndexDoc) {
        try {
            final SolrClient solrClient = new SolrClientFactory().create(
                    solrIndexDoc.getSolrConnectionConfig());
            final FieldTypesResponse response = new FieldTypes().process(
                    solrClient, solrIndexDoc.getCollection());
            return response.getFieldTypes()
                    .stream()
                    .map(fieldTypeRepresentation ->
                            Optional.ofNullable(fieldTypeRepresentation.getAttributes()))
                    .filter(Optional::isPresent)
                    .map(optional -> Optional.ofNullable(optional.get().get("name")))
                    .filter(Optional::isPresent)
                    .map(optional -> (String) optional.get())
                    .collect(Collectors.toList());
        } catch (final IOException | SolrServerException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Override
    public SolrConnectionTestResponse solrConnectionTest(final SolrIndexDoc solrIndexDoc) {
        try {
            final SolrClient solrClient = new SolrClientFactory().create(
                    solrIndexDoc.getSolrConnectionConfig());
//            final SolrPingResponse response = new SolrPing()
//            .process(solrClient, action.getSolrIndex().getCollection());
            final SolrPingResponse response = solrClient.ping();

            final StringBuilder sb = new StringBuilder();
            sb.append("Request URL: ");
            sb.append(response.getRequestUrl());
            sb.append("\nStatus: ");
            sb.append(response.getStatus());
            sb.append("\nElapsed Time: ");
            sb.append(ModelStringUtil.formatDurationString(response.getElapsedTime()));
            sb.append("\nQ Time: ");
            sb.append(ModelStringUtil.formatDurationString((long) response.getQTime()));

            sb.append("\nResponse Header: ");
            sb.append(response.getResponseHeader().toString());
            sb.append("\nResponse: ");
            sb.append(response.getResponse().toString());

            if (response.getException() != null) {
                sb.append("\nError: ");
                sb.append(response.getException().toString());
            }

            return new SolrConnectionTestResponse(true, sb.toString());

        } catch (final IOException | SolrServerException | RuntimeException e) {
            return new SolrConnectionTestResponse(false, e.getMessage());
        }
    }
}

@@ -702,16 +702,63 @@
 Helper;%0A
+import stroom.event.logging.rs.api.AutoLogged;%0A
 import s
@@ -955,24 +955,65 @@
 eException;%0A
+import stroom.util.shared.FetchWithUuid;%0A
 import stroo
@@ -1520,16 +1520,28 @@
 nject;%0A%0A
+@AutoLogged%0A
 class So
@@ -1588,16 +1588,45 @@
 Resource
+, FetchWithUuid%3CSolrIndexDoc%3E
  %7B%0A%0A    

Apply @AutoLogged to improve standards compliance of SolrIndexResourceImpl