/*
 * Copyright 2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.frontend.find.core.savedsearches.query;

import com.hp.autonomy.frontend.find.core.savedsearches.ConceptClusterPhrase;
import com.hp.autonomy.frontend.find.core.savedsearches.FieldTextParser;
import com.hp.autonomy.frontend.find.core.search.QueryRestrictionsBuilderFactory;
import com.hp.autonomy.searchcomponents.core.search.DocumentsService;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictions;
import com.hp.autonomy.searchcomponents.core.search.SearchRequest;
import com.hp.autonomy.searchcomponents.core.search.SearchResult;
import com.hp.autonomy.types.requests.Documents;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.Serializable;
import java.util.Collections;

import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public abstract class SavedQueryControllerTest<S extends Serializable, Q extends QueryRestrictions<S>, D extends SearchResult, E extends Exception> {
    @Mock
    protected SavedQueryService savedQueryService;
    @Mock
    protected DocumentsService<S, D, E> documentsService;
    @Mock
    protected FieldTextParser fieldTextParser;
    @Mock
    private Documents<D> searchResults;
    @Mock
    protected QueryRestrictionsBuilderFactory<Q, S> queryRestrictionsBuilderFactory;

    private SavedQueryController<S, Q, D, E> savedQueryController;

    private final SavedQuery savedQuery = new SavedQuery.Builder()
            .setTitle("Any old saved search")
            .build();

    protected abstract SavedQueryController<S, Q, D, E> constructController();

    @Before
    public void setUp() {
        savedQueryController = constructController();
    }

    @Test
    public void create() {
        savedQueryController.create(savedQuery);
        verify(savedQueryService).create(Matchers.same(savedQuery));
    }

    @Test
    public void update() {
        when(savedQueryService.update(any(SavedQuery.class))).then(returnsFirstArg());

        final SavedQuery updatedQuery = savedQueryController.update(42, savedQuery);
        verify(savedQueryService).update(Matchers.isA(SavedQuery.class));
        assertEquals(42L, (long) updatedQuery.getId());
    }

    @Test
    public void getAll() {
        savedQueryController.getAll();
        verify(savedQueryService).getAll();
    }

    @Test
    public void delete() {
        savedQueryController.delete(42L);
        verify(savedQueryService).deleteById(eq(42L));
    }

    @Test
    public void checkForNewQueryResults() throws E {
        final long id = 123L;
        final SavedQuery savedQuery = new SavedQuery.Builder()
                .setId(id)
                .setConceptClusterPhrases(Collections.singleton(new ConceptClusterPhrase()))
                .build();
        when(savedQueryService.get(id)).thenReturn(savedQuery);
        int numberOfResults = 1;
        when(searchResults.getTotalResults()).thenReturn(numberOfResults);
        when(documentsService.queryTextIndex(Matchers.<SearchRequest<S>>any())).thenReturn(searchResults);
        assertEquals(numberOfResults, savedQueryController.checkForNewQueryResults(id));
    }

    @Test
    public void checkForNewQueryResultsNoNewResults() throws E {
        final long id = 123L;
        final SavedQuery savedQuery = new SavedQuery.Builder()
                .setId(id)
                .setConceptClusterPhrases(Collections.singleton(new ConceptClusterPhrase()))
                .build();
        when(savedQueryService.get(id)).thenReturn(savedQuery);
        final int numberOfResults = 0;
        when(documentsService.queryTextIndex(Matchers.<SearchRequest<S>>any())).thenReturn(searchResults);
        assertEquals(numberOfResults, savedQueryController.checkForNewQueryResults(id));
    }

    @Test
    public void checkForNewQueryResultsButIncompatibleRestrictions() throws E {
        final long id = 123L;
        final DateTime lastFetchTime = DateTime.now();
        final SavedQuery savedQuery = new SavedQuery.Builder()
                .setDateNewDocsLastFetched(lastFetchTime)
                .setId(id)
                .setMaxDate(lastFetchTime.minus(1))
                .build();
        when(savedQueryService.get(id)).thenReturn(savedQuery);
        final int numberOfResults = 0;

        assertEquals(numberOfResults, savedQueryController.checkForNewQueryResults(id));
        verify(documentsService, never()).queryTextIndex(Matchers.<SearchRequest<S>>any());
    }
}

@@ -176,17 +176,16 @@
 se.%0A */%0A
-%0A
 package 
@@ -1479,16 +1479,151 @@
 tion%3E %7B%0A
+    private final SavedQuery savedQuery = new SavedQuery.Builder()%0A            .setTitle(%22Any old saved search%22)%0A            .build();%0A
     @Moc
@@ -1814,58 +1814,8 @@
 ock%0A
-    private Documents%3CD%3E searchResults;%0A    @Mock%0A
     
@@ -1895,16 +1895,25 @@
 actory;%0A
+    @Mock
 %0A    pri
@@ -1921,63 +1921,35 @@
 ate 
-SavedQueryController%3CS, Q, D, E%3E savedQueryController;%0A
+Documents%3CD%3E searchResults;
 %0A   
@@ -1949,38 +1949,32 @@
 ts;%0A    private 
-final 
 SavedQuery saved
@@ -1971,113 +1971,51 @@
 uery
- savedQuery = new SavedQuery.Builder()%0A            .setTitle(%22Any old saved search%22)%0A            .build()
+Controller%3CS, Q, D, E%3E savedQueryController
 ;%0A%0A 
@@ -2670,17 +2670,16 @@
 , (long)
- 
 updatedQ
@@ -3232,32 +3232,51 @@
 ptClusterPhrase(
+%22raccoons%22, true, 0
 )))%0A            
@@ -3948,16 +3948,35 @@
 rPhrase(
+%22raccoons%22, true, 0
 )))%0A    

Fix broken test