/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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 org.apache.atlas.catalog;

import org.apache.atlas.catalog.exception.CatalogException;
import org.apache.atlas.catalog.exception.InvalidPayloadException;
import org.apache.atlas.catalog.exception.ResourceAlreadyExistsException;
import org.apache.atlas.catalog.exception.ResourceNotFoundException;
import org.apache.atlas.catalog.query.AtlasQuery;
import org.apache.atlas.catalog.query.QueryFactory;
import org.easymock.Capture;
import org.testng.annotations.Test;

import java.util.*;

import static org.easymock.EasyMock.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;

/**
 * Unit tests for EntityTagResourceProvider.
 */
public class EntityTagResourceProviderTest {
    @Test
    public void testGetResource() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        Capture<Request> requestCapture = newCapture();

        Collection<Map<String, Object>> queryResult = new ArrayList<>();
        Map<String, Object> queryResultRow = new HashMap<>();
        queryResult.add(queryResultRow);
        queryResultRow.put("name", "taxonomyName.termName");
        queryResultRow.put("description", "test term description");

        // mock expectations
        expect(queryFactory.createEntityTagQuery(capture(requestCapture))).andReturn(query);
        expect(query.execute()).andReturn(queryResult);
        replay(typeSystem, queryFactory, query);

        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "taxonomyName.termName");
        requestProperties.put("id", "1");
        Request userRequest = new InstanceRequest(requestProperties);

        Result result = provider.getResourceById(userRequest);

        assertEquals(1, result.getPropertyMaps().size());
        assertEquals(queryResultRow, result.getPropertyMaps().iterator().next());

        Request request = requestCapture.getValue();
        assertNull(request.getQueryString());
        assertEquals(0, request.getAdditionalSelectProperties().size());
        assertEquals(2, request.getQueryProperties().size());
        assertEquals("taxonomyName.termName", request.getQueryProperties().get("name"));
        assertEquals(Request.Cardinality.INSTANCE, request.getCardinality());

        verify(typeSystem, queryFactory, query);
    }

    @Test(expectedExceptions = ResourceNotFoundException.class)
    public void testGetResource_404() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        Capture<Request> requestCapture = newCapture();

        // empty response should result in a ResourceNotFoundException
        Collection<Map<String, Object>> emptyResponse = new ArrayList<>();

        // mock expectations
        expect(queryFactory.createEntityTagQuery(capture(requestCapture))).andReturn(query);
        expect(query.execute()).andReturn(emptyResponse);
        replay(typeSystem, queryFactory, query);

        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "taxonomyName.termName");
        requestProperties.put("id", "1");
        Request request = new InstanceRequest(requestProperties);

        provider.getResourceById(request);
    }

    @Test
    public void testGetResources() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        Capture<Request> requestCapture = newCapture();

        Collection<Map<String, Object>> queryResult = new ArrayList<>();
        Map<String, Object> queryResultRow1 = new HashMap<>();
        queryResult.add(queryResultRow1);
        queryResultRow1.put("name", "testTaxonomy.termName");
        queryResultRow1.put("description", "test term description");

        Map<String, Object> queryResultRow2 = new HashMap<>();
        queryResult.add(queryResultRow2);
        queryResultRow2.put("name", "testTaxonomy.termName2");
        queryResultRow2.put("description", "test term 2 description");
        // mock expectations
        expect(queryFactory.createEntityTagQuery(capture(requestCapture))).andReturn(query);
        expect(query.execute()).andReturn(queryResult);
        replay(typeSystem, queryFactory, query);

        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("id", "1");
        Request userRequest = new CollectionRequest(requestProperties, "name:testTaxonomy.*");
        // invoke test method
        Result result = provider.getResources(userRequest);

        assertEquals(2, result.getPropertyMaps().size());
        assertTrue(result.getPropertyMaps().contains(queryResultRow1));
        assertTrue(result.getPropertyMaps().contains(queryResultRow2));

        Request request = requestCapture.getValue();
        assertEquals("name:testTaxonomy.*", request.getQueryString());
        assertEquals(0, request.getAdditionalSelectProperties().size());

        verify(typeSystem, queryFactory, query);
    }

    @Test
    public void testGetResources_noResults() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        Capture<Request> requestCapture = newCapture();

        Collection<Map<String, Object>> queryResult = new ArrayList<>();

        // mock expectations
        expect(queryFactory.createEntityTagQuery(capture(requestCapture))).andReturn(query);
        expect(query.execute()).andReturn(queryResult);
        replay(typeSystem, queryFactory, query);

        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("id", "1");
        Request userRequest = new CollectionRequest(requestProperties, "name:testTaxonomy.*");
        // invoke test method
        Result result = provider.getResources(userRequest);

        assertEquals(0, result.getPropertyMaps().size());

        Request request = requestCapture.getValue();
        assertEquals("name:testTaxonomy.*", request.getQueryString());
        assertEquals(0, request.getAdditionalSelectProperties().size());

        verify(typeSystem, queryFactory, query);
    }

    @Test(expectedExceptions = InvalidPayloadException.class)
    public void testCreateResource_invalidRequest__noName() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);

        replay(typeSystem, queryFactory, query);

        Map<String, Object> requestProperties = new HashMap<>();
        // missing name name should result in InvalidPayloadException
        requestProperties.put("description", "description");
        Request userRequest = new InstanceRequest(requestProperties);

        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(queryFactory);

        provider.createResource(userRequest);
    }

    @Test
    public void testCreateResource() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        ResourceProvider termResourceProvider = createStrictMock(TermResourceProvider.class);
        Capture<Request> termRequestCapture = newCapture();

        Collection<Map<String, Object>> termQueryResult = new ArrayList<>();
        Map<String, Object> termQueryResultRow = new HashMap<>();
        termQueryResult.add(termQueryResultRow);
        termQueryResultRow.put("name", "testTaxonomy.termName");
        termQueryResultRow.put("type", "testTaxonomy.termName");
        termQueryResultRow.put("available_as_tag", true);
        termQueryResultRow.put("description", "term description");
        Result termResult = new Result(termQueryResult);

        // mock expectations
        expect(termResourceProvider.getResourceById(capture(termRequestCapture))).andReturn(termResult);
        Map<String, Object> tagProperties = new HashMap<>();
        tagProperties.put("name", "testTaxonomy.termName");
        tagProperties.put("description", "term description");
        typeSystem.createTraitInstance("11-22-33", "testTaxonomy.termName", tagProperties);
        replay(typeSystem, queryFactory, query, termResourceProvider);

        EntityTagResourceProvider provider = new TestEntityTagResourceProvider(typeSystem, termResourceProvider);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "testTaxonomy.termName");
        requestProperties.put("id", "11-22-33");
        Request userRequest = new InstanceRequest(requestProperties);

        provider.createResource(userRequest);

        Request termRequest = termRequestCapture.getValue();
        Map<String, Object> termRequestProps = termRequest.getQueryProperties();
        assertEquals(1, termRequestProps.size());
        TermPath termPath = (TermPath) termRequestProps.get("termPath");
        assertEquals("testTaxonomy.termName", termPath.getFullyQualifiedName());
        assertEquals(1, termRequest.getAdditionalSelectProperties().size());
        assertEquals("type", termRequest.getAdditionalSelectProperties().iterator().next());
        assertNull(termRequest.getQueryString());

        verify(typeSystem, queryFactory, query, termResourceProvider);
    }

    @Test(expectedExceptions = CatalogException.class)
    public void testCreateResource_invalidRequest__termNotAvailableForTagging() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        ResourceProvider termResourceProvider = createStrictMock(TermResourceProvider.class);
        Capture<Request> termRequestCapture = newCapture();

        Collection<Map<String, Object>> termQueryResult = new ArrayList<>();
        Map<String, Object> termQueryResultRow = new HashMap<>();
        termQueryResult.add(termQueryResultRow);
        termQueryResultRow.put("name", "testTaxonomy.termName");
        termQueryResultRow.put("type", "testTaxonomy.termName");
        // false value for 'available_as_tag' should result in an exception
        termQueryResultRow.put("available_as_tag", false);
        termQueryResultRow.put("description", "term description");
        Result termResult = new Result(termQueryResult);

        // mock expectations
        expect(termResourceProvider.getResourceById(capture(termRequestCapture))).andReturn(termResult);
        replay(typeSystem, queryFactory, query, termResourceProvider);

        EntityTagResourceProvider provider = new TestEntityTagResourceProvider(typeSystem, termResourceProvider);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "testTaxonomy.termName");
        requestProperties.put("id", "11-22-33");
        Request userRequest = new InstanceRequest(requestProperties);

        provider.createResource(userRequest);
    }

    @Test(expectedExceptions = ResourceAlreadyExistsException.class)
    public void testCreateResource_invalidRequest__alreadyExists() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery query = createStrictMock(AtlasQuery.class);
        ResourceProvider termResourceProvider = createStrictMock(TermResourceProvider.class);
        Capture<Request> termRequestCapture = newCapture();

        Collection<Map<String, Object>> termQueryResult = new ArrayList<>();
        Map<String, Object> termQueryResultRow = new HashMap<>();
        termQueryResult.add(termQueryResultRow);
        termQueryResultRow.put("name", "testTaxonomy.termName");
        termQueryResultRow.put("type", "testTaxonomy.termName");
        termQueryResultRow.put("available_as_tag", true);
        termQueryResultRow.put("description", "term description");
        Result termResult = new Result(termQueryResult);

        // mock expectations
        expect(termResourceProvider.getResourceById(capture(termRequestCapture))).andReturn(termResult);
        Map<String, Object> tagProperties = new HashMap<>();
        tagProperties.put("name", "testTaxonomy.termName");
        tagProperties.put("description", "term description");
        typeSystem.createTraitInstance("11-22-33", "testTaxonomy.termName", tagProperties);
        expectLastCall().andThrow(new ResourceAlreadyExistsException(""));
        replay(typeSystem, queryFactory, query, termResourceProvider);

        EntityTagResourceProvider provider = new TestEntityTagResourceProvider(typeSystem, termResourceProvider);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "testTaxonomy.termName");
        requestProperties.put("id", "11-22-33");
        Request userRequest = new InstanceRequest(requestProperties);

        provider.createResource(userRequest);
    }

    @Test
    public void testCreateResources() throws Exception {
        AtlasTypeSystem typeSystem = createMock(AtlasTypeSystem.class);
        QueryFactory queryFactory = createStrictMock(QueryFactory.class);
        AtlasQuery entityQuery = createMock(AtlasQuery.class);
        ResourceProvider termResourceProvider = createMock(TermResourceProvider.class);
        Capture<Request> entityRequestCapture = newCapture();
        Capture<Request> termRequestCapture1 = newCapture();
        Capture<Request> termRequestCapture2 = newCapture();

        Collection<Map<String, Object>> entityQueryResult = new ArrayList<>();
        Map<String, Object> entityQueryResultRow = new HashMap<>();
        entityQueryResultRow.put("id", "1");
        entityQueryResult.add(entityQueryResultRow);

        Map<String, Object> entityQueryResultRow2 = new HashMap<>();
        entityQueryResultRow2.put("id", "2");
        entityQueryResult.add(entityQueryResultRow2);

        Collection<Map<String, Object>> termQueryResult1 = new ArrayList<>();
        Map<String, Object> termQueryResultRow1 = new HashMap<>();
        termQueryResult1.add(termQueryResultRow1);
        termQueryResultRow1.put("name", "testTaxonomy.termName1");
        termQueryResultRow1.put("type", "testTaxonomy.termName1");
        termQueryResultRow1.put("available_as_tag", true);
        termQueryResultRow1.put("description", "term description");
        Result termResult1 = new Result(termQueryResult1);

        Collection<Map<String, Object>> termQueryResult2 = new ArrayList<>();
        Map<String, Object> termQueryResultRow2 = new HashMap<>();
        termQueryResult2.add(termQueryResultRow2);
        termQueryResultRow2.put("name", "testTaxonomy.termName2");
        termQueryResultRow2.put("type", "testTaxonomy.termName2");
        termQueryResultRow2.put("available_as_tag", true);
        termQueryResultRow2.put("description", "term 2 description");
        Result termResult2 = new Result(termQueryResult2);

        // mock expectations
        expect(queryFactory.createEntityQuery(capture(entityRequestCapture))).andReturn(entityQuery);
        expect(entityQuery.execute()).andReturn(entityQueryResult);

        expect(termResourceProvider.getResourceById(capture(termRequestCapture1))).andReturn(termResult1);
        expect(termResourceProvider.getResourceById(capture(termRequestCapture2))).andReturn(termResult2);

        Map<String, Object> tagProperties1 = new HashMap<>();
        tagProperties1.put("name", "testTaxonomy.termName1");
        tagProperties1.put("description", "term description");
        // each tag is associated with each entity
        typeSystem.createTraitInstance("1", "testTaxonomy.termName1", tagProperties1);
        typeSystem.createTraitInstance("2", "testTaxonomy.termName1", tagProperties1);

        Map<String, Object> tagProperties2 = new HashMap<>();
        tagProperties2.put("name", "testTaxonomy.termName2");
        tagProperties2.put("description", "term 2 description");
        // each tag is associated with each entity
        typeSystem.createTraitInstance("1", "testTaxonomy.termName2", tagProperties2);
        typeSystem.createTraitInstance("2", "testTaxonomy.termName2", tagProperties2);

        replay(typeSystem, queryFactory, entityQuery, termResourceProvider);
        // end mock expectations

        EntityTagResourceProvider provider = new TestEntityTagResourceProvider(typeSystem, termResourceProvider);
        provider.setQueryFactory(queryFactory);

        Map<String, Object> requestProps = new HashMap<>();
        Collection<Map<String, String>> tagMaps = new ArrayList<>();
        requestProps.put("tags", tagMaps);
        Map<String, String> tagMap1 = new HashMap<>();
        tagMap1.put("name", "testTaxonomy.termName1");
        tagMaps.add(tagMap1);
        Map<String, String> tagMap2 = new HashMap<>();
        tagMap2.put("name", "testTaxonomy.termName2");
        tagMaps.add(tagMap2);

        Request userRequest = new CollectionRequest(requestProps, "name:foo*");
        // invoke method being tested
        Collection<String> createResult = provider.createResources(userRequest);

        assertEquals(4, createResult.size());
        assertTrue(createResult.contains("v1/entities/1/tags/testTaxonomy.termName1"));
        assertTrue(createResult.contains("v1/entities/1/tags/testTaxonomy.termName2"));
        assertTrue(createResult.contains("v1/entities/2/tags/testTaxonomy.termName1"));
        assertTrue(createResult.contains("v1/entities/2/tags/testTaxonomy.termName2"));

        Request entityRequest = entityRequestCapture.getValue();
        assertEquals("name:foo*", entityRequest.getQueryString());
        assertEquals(Request.Cardinality.COLLECTION, entityRequest.getCardinality());

        Request termRequest1 = termRequestCapture1.getValue();
        assertNull(termRequest1.getQueryString());
        assertEquals(Request.Cardinality.INSTANCE, termRequest1.getCardinality());
        Map<String, Object> termRequestProps = termRequest1.getQueryProperties();
        assertEquals(1, termRequestProps.size());
        TermPath termPath = (TermPath) termRequestProps.get("termPath");
        assertEquals("testTaxonomy.termName1", termPath.getFullyQualifiedName());

        Request termRequest2 = termRequestCapture2.getValue();
        assertNull(termRequest2.getQueryString());
        assertEquals(Request.Cardinality.INSTANCE, termRequest2.getCardinality());
        Map<String, Object> termRequestProps2 = termRequest2.getQueryProperties();
        assertEquals(1, termRequestProps2.size());
        TermPath termPath2 = (TermPath) termRequestProps2.get("termPath");
        assertEquals("testTaxonomy.termName2", termPath2.getFullyQualifiedName());

        verify(typeSystem, queryFactory, entityQuery, termResourceProvider);
    }

    @Test
    public void testDeleteResourceById() throws Exception {
        AtlasTypeSystem typeSystem = createStrictMock(AtlasTypeSystem.class);

        // mock expectations
        typeSystem.deleteTag("1", "taxonomyName.termName");
        replay(typeSystem);

        Map<String, Object> requestProperties = new HashMap<>();
        requestProperties.put("name", "taxonomyName.termName");
        requestProperties.put("id", "1");
        Request userRequest = new InstanceRequest(requestProperties);

        // instantiate EntityTagResourceProvider and invoke method being tested
        EntityTagResourceProvider provider = new EntityTagResourceProvider(typeSystem);
        provider.setQueryFactory(null);
        provider.deleteResourceById(userRequest);

        verify(typeSystem);
    }

    //todo: test behavior of createResources in case of partial success after behavior is defined


    private static class TestEntityTagResourceProvider extends EntityTagResourceProvider {

        private ResourceProvider testTermResourceProvider;

        public TestEntityTagResourceProvider(AtlasTypeSystem typeSystem, ResourceProvider termResourceProvider) {
            super(typeSystem);
            testTermResourceProvider = termResourceProvider;
        }

        @Override
        protected synchronized ResourceProvider getTermResourceProvider() {
            return testTermResourceProvider;
        }
    }
}
