/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License;
 * you may not use this file except in compliance with the Elastic License.
 */
package org.elasticsearch.xpack.rollup.action;


import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.test.AbstractStreamableTestCase;
import org.elasticsearch.xpack.core.rollup.ConfigTestHelpers;
import org.elasticsearch.xpack.core.rollup.RollupField;
import org.elasticsearch.xpack.core.rollup.action.GetRollupIndexCapsAction;
import org.elasticsearch.xpack.core.rollup.action.RollableIndexCaps;
import org.mockito.Mockito;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static org.elasticsearch.xpack.rollup.action.TransportGetRollupIndexCapsAction.getCapsByRollupIndex;
import static org.hamcrest.Matchers.equalTo;


public class GetRollupIndexCapsActionRequestTests extends AbstractStreamableTestCase<GetRollupIndexCapsAction.Request> {

    @Override
    protected GetRollupIndexCapsAction.Request createTestInstance() {
        if (randomBoolean()) {
            return new GetRollupIndexCapsAction.Request(new String[]{MetaData.ALL});
        }
        return new GetRollupIndexCapsAction.Request(new String[]{randomAlphaOfLengthBetween(1, 20)});
    }

    @Override
    protected GetRollupIndexCapsAction.Request createBlankInstance() {
        return new GetRollupIndexCapsAction.Request();
    }


    public void testNoIndicesByRollup() {
        ImmutableOpenMap<String, IndexMetaData> indices = new ImmutableOpenMap.Builder<String, IndexMetaData>().build();
        Map<String, RollableIndexCaps> caps = getCapsByRollupIndex(Collections.singletonList("foo"), indices);
        assertThat(caps.size(), equalTo(0));
    }

    public void testAllIndicesByRollupSingleRollup() throws IOException {
        int num = randomIntBetween(1,5);
        ImmutableOpenMap.Builder<String, IndexMetaData> indices = new ImmutableOpenMap.Builder<>(5);
        int indexCounter = 0;
        for (int j = 0; j < 5; j++) {

            Map<String, Object> jobs = new HashMap<>(num);
            for (int i = 0; i < num; i++) {
                String jobName = randomAlphaOfLength(10);
                String indexName = Integer.toString(indexCounter);
                indexCounter += 1;
                jobs.put(jobName, ConfigTestHelpers.randomRollupJobConfig(random(), jobName, indexName, "foo"));
            }

            MappingMetaData mappingMeta = new MappingMetaData(RollupField.TYPE_NAME,
                Collections.singletonMap(RollupField.TYPE_NAME,
                    Collections.singletonMap("_meta",
                        Collections.singletonMap(RollupField.ROLLUP_META, jobs))));

            ImmutableOpenMap.Builder<String, MappingMetaData> mappings = ImmutableOpenMap.builder(1);
            mappings.put(RollupField.TYPE_NAME, mappingMeta);
            IndexMetaData meta = Mockito.mock(IndexMetaData.class);
            Mockito.when(meta.getMappings()).thenReturn(mappings.build());
            indices.put("foo", meta);
        }

        Map<String, RollableIndexCaps> caps = getCapsByRollupIndex(Collections.singletonList("foo"),
            indices.build());
        assertThat(caps.size(), equalTo(1));
    }

    public void testAllIndicesByRollupManyRollup() throws IOException {
        ImmutableOpenMap.Builder<String, IndexMetaData> indices = new ImmutableOpenMap.Builder<>(5);
        int indexCounter = 0;
        for (int j = 0; j < 5; j++) {

            Map<String, Object> jobs = new HashMap<>(1);
            String jobName = randomAlphaOfLength(10);
            String indexName = Integer.toString(indexCounter);
            indexCounter += 1;
            jobs.put(jobName, ConfigTestHelpers.randomRollupJobConfig(random(), jobName, indexName, "rollup_" + indexName));

            MappingMetaData mappingMeta = new MappingMetaData(RollupField.TYPE_NAME,
                Collections.singletonMap(RollupField.TYPE_NAME,
                    Collections.singletonMap("_meta",
                        Collections.singletonMap(RollupField.ROLLUP_META, jobs))));

            ImmutableOpenMap.Builder<String, MappingMetaData> mappings = ImmutableOpenMap.builder(1);
            mappings.put(RollupField.TYPE_NAME, mappingMeta);
            IndexMetaData meta = Mockito.mock(IndexMetaData.class);
            Mockito.when(meta.getMappings()).thenReturn(mappings.build());
            indices.put("rollup_" + indexName, meta);
        }

        Map<String, RollableIndexCaps> caps = getCapsByRollupIndex(Arrays.asList(indices.keys().toArray(String.class)), indices.build());
        assertThat(caps.size(), equalTo(5));
    }


    public void testOneIndexByRollupManyRollup() throws IOException {
        ImmutableOpenMap.Builder<String, IndexMetaData> indices = new ImmutableOpenMap.Builder<>(5);
        int indexCounter = 0;
        for (int j = 0; j < 5; j++) {

            Map<String, Object> jobs = new HashMap<>(1);
            String jobName = randomAlphaOfLength(10);
            String indexName = Integer.toString(indexCounter);
            indexCounter += 1;
            jobs.put(jobName, ConfigTestHelpers.randomRollupJobConfig(random(), jobName, "foo_" + indexName, "rollup_" + indexName));

            MappingMetaData mappingMeta = new MappingMetaData(RollupField.TYPE_NAME,
                Collections.singletonMap(RollupField.TYPE_NAME,
                    Collections.singletonMap("_meta",
                        Collections.singletonMap(RollupField.ROLLUP_META, jobs))));

            ImmutableOpenMap.Builder<String, MappingMetaData> mappings = ImmutableOpenMap.builder(1);
            mappings.put(RollupField.TYPE_NAME, mappingMeta);
            IndexMetaData meta = Mockito.mock(IndexMetaData.class);
            Mockito.when(meta.getMappings()).thenReturn(mappings.build());
            indices.put("rollup_" + indexName, meta);
        }

        Map<String, RollableIndexCaps> caps = getCapsByRollupIndex(Collections.singletonList("rollup_1"), indices.build());
        assertThat(caps.size(), equalTo(1));
        assertThat(caps.get("rollup_1").getIndexName(), equalTo("rollup_1"));
        assertThat(caps.get("rollup_1").getJobCaps().size(), equalTo(1));
    }

    public void testOneIndexByRollupOneRollup() throws IOException {
        ImmutableOpenMap.Builder<String, IndexMetaData> indices = new ImmutableOpenMap.Builder<>(5);
        int indexCounter = 0;
        for (int j = 0; j < 5; j++) {

            Map<String, Object> jobs = new HashMap<>(1);
            String jobName = randomAlphaOfLength(10);
            String indexName = Integer.toString(indexCounter);
            indexCounter += 1;
            jobs.put(jobName, ConfigTestHelpers.randomRollupJobConfig(random(), jobName, "foo_" + indexName, "rollup_foo"));

            MappingMetaData mappingMeta = new MappingMetaData(RollupField.TYPE_NAME,
                Collections.singletonMap(RollupField.TYPE_NAME,
                    Collections.singletonMap("_meta",
                        Collections.singletonMap(RollupField.ROLLUP_META, jobs))));

            ImmutableOpenMap.Builder<String, MappingMetaData> mappings = ImmutableOpenMap.builder(1);
            mappings.put(RollupField.TYPE_NAME, mappingMeta);
            IndexMetaData meta = Mockito.mock(IndexMetaData.class);
            Mockito.when(meta.getMappings()).thenReturn(mappings.build());
            indices.put("rollup_foo", meta);
        }

        Map<String, RollableIndexCaps> caps = getCapsByRollupIndex(Collections.singletonList("rollup_foo"), indices.build());
        assertThat(caps.size(), equalTo(1));
        assertThat(caps.get("rollup_foo").getIndexName(), equalTo("rollup_foo"));
        assertThat(caps.get("rollup_foo").getJobCaps().size(), equalTo(1));
    }
}


