/*
 * Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  Crate 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
 *
 *   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.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial agreement.
 */

package io.crate.integrationtests;

import io.crate.blob.v2.BlobAdminClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESIntegTestCase;
import org.junit.Test;

import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;

@ESIntegTestCase.ClusterScope(numDataNodes = 2)
public class ShardStatsTest extends SQLTransportIntegrationTest {

    @Test
    public void testSelectZeroLimit() throws Exception {
        execute("create table test (col1 int) clustered into 3 shards with (number_of_replicas=0)");
        ensureGreen();
        execute("select * from sys.shards limit 0");
        assertEquals(0L, response.rowCount());
    }

    @Test
    public void testShardSelect() throws Exception {
        execute("create table test (col1 int) clustered into 3 shards with (number_of_replicas=0)");
        ensureGreen();

        execute("select count(*) from sys.shards where table_name='test'");
        assertEquals(1, response.rowCount());
        assertEquals(3L, response.rows()[0][0]);
    }

    @Test
    public void testSelectIncludingUnassignedShards() throws Exception {
        execute("create table locations (id integer primary key, name string) " +
                "clustered into 2 shards " +
                "with (number_of_replicas=2, \"write.wait_for_active_shards\"=1)");
        client().admin().cluster().prepareHealth("locations").setWaitForYellowStatus().execute().actionGet();

        execute("select state, \"primary\", recovery from sys.shards where table_name = 'locations' order by state, \"primary\"");
        assertEquals(6L, response.rowCount());
        for (int i = 4; i < response.rowCount(); i++) {
            Object[] row = response.rows()[i];
            assertEquals("UNASSIGNED", row[0]);
            assertEquals(false, row[1]);
            assertEquals(null, row[2]);
        }
    }

    @Test
    public void testSelectGroupByIncludingUnassignedShards() throws Exception {
        execute("create table locations (id integer primary key, name string) " +
                "clustered into 5 shards " +
                "with(number_of_replicas=2 , \"write.wait_for_active_shards\"=1)");
        ensureYellow();

        execute("select count(*), state, \"primary\" from sys.shards " +
                "group by state, \"primary\" order by state desc");
        assertThat(response.rowCount(), greaterThanOrEqualTo(2L));
        assertEquals(3, response.cols().length);
        assertThat((Long) response.rows()[0][0], greaterThanOrEqualTo(5L));
        assertEquals("UNASSIGNED", response.rows()[0][1]);
        assertEquals(false, response.rows()[0][2]);
    }

    @Test
    public void testSelectCountIncludingUnassignedShards() throws Exception {
        execute("create table locations (id integer primary key, name string) " +
                "clustered into 5 shards " +
                "with(number_of_replicas=2, \"write.wait_for_active_shards\"=1)");
        ensureYellow();

        execute("select count(*) from sys.shards where table_name='locations'");
        assertThat(response.rowCount(), is(1L));
        assertThat((Long) response.rows()[0][0], is(15L));
    }

    @Test
    public void testTableNameBlobTable() throws Exception {
        BlobAdminClient blobAdminClient = internalCluster().getInstance(BlobAdminClient.class);
        Settings indexSettings = Settings.builder()
            .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
            .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
            .build();
        blobAdminClient.createBlobTable("blobs", indexSettings).get();
        ensureGreen();

        execute("select schema_name, table_name from sys.shards where table_name = 'blobs'");
        assertThat(response.rowCount(), is(2L));
        for (int i = 0; i < response.rowCount(); i++) {
            assertThat((String) response.rows()[i][0], is("blob"));
            assertThat((String) response.rows()[i][1], is("blobs"));
        }

        execute("create blob table sbolb clustered into 4 shards " +
            "with (number_of_replicas=0)");
        ensureYellow();

        execute("select schema_name, table_name from sys.shards where table_name = 'sbolb'");
        assertThat(response.rowCount(), is(4L));
        for (int i = 0; i < response.rowCount(); i++) {
            assertThat((String) response.rows()[i][0], is("blob"));
            assertThat((String) response.rows()[i][1], is("sbolb"));
        }
        execute("select count(*) from sys.shards " +
                "where schema_name='blob' and table_name != 'blobs' " +
                "and table_name != 'sbolb'");
        assertThat(response.rowCount(), is(1L));
        assertThat((Long) response.rows()[0][0], is(0L));
    }
}

@@ -1270,16 +1270,76 @@
 .Test;%0A%0A
+import static io.crate.testing.TestingHelpers.printedTable;%0A
 import s
@@ -2502,24 +2502,25 @@
 %22=1)%22);%0A
+%0A
         
 client()
@@ -2515,111 +2515,31 @@
     
-client().admin().cluster().prepareHealth(%22locations%22).setWaitForYellowStatus().execute().actionGet();%0A%0A
+assertBusy(() -%3E %7B%0A    
     
@@ -2586,16 +2586,25 @@
 recovery
+%5B'stage'%5D
  from sy
@@ -2686,25 +2686,53 @@
     
+    
 assert
-Equals(6L, 
+That(%0A                printedTable(
 resp
@@ -2735,33 +2735,29 @@
 response.row
-Count());
+s()),
 %0A        for
@@ -2757,229 +2757,291 @@
     
-for (int i = 4; i %3C response.rowCount(); i++) %7B%0A            Object%5B%5D row = response.rows()%5Bi%5D;%0A            assertEquals(%22UNASSIGNED%22, row%5B0%5D);%0A            assertEquals(false, row%5B1%5D);%0A            assertEquals(null, row%5B2%5D
+        is(%22STARTED%7C false%7C DONE%5Cn%22 +%0A                   %22STARTED%7C false%7C DONE%5Cn%22 +%0A                   %22STARTED%7C true%7C DONE%5Cn%22 +%0A                   %22STARTED%7C true%7C DONE%5Cn%22 +%0A                   %22UNASSIGNED%7C false%7C NULL%5Cn%22 +%0A                   %22UNASSIGNED%7C false%7C NULL%5Cn%22)%0A            
 );%0A 
@@ -3044,24 +3044,26 @@
 );%0A        %7D
+);
 %0A    %7D%0A%0A    

Make testSelectIncludingUnassignedShards fast