/*
 * 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
 *
 *     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 org.apache.shardingsphere.scaling.core.api.impl;

import org.apache.shardingsphere.governance.repository.api.config.GovernanceCenterConfiguration;
import org.apache.shardingsphere.governance.repository.api.config.GovernanceConfiguration;
import org.apache.shardingsphere.scaling.core.api.JobInfo;
import org.apache.shardingsphere.scaling.core.api.ScalingAPI;
import org.apache.shardingsphere.scaling.core.api.ScalingAPIFactory;
import org.apache.shardingsphere.scaling.core.config.ScalingContext;
import org.apache.shardingsphere.scaling.core.config.ServerConfiguration;
import org.apache.shardingsphere.scaling.core.fixture.EmbedTestingServer;
import org.apache.shardingsphere.scaling.core.job.JobStatus;
import org.apache.shardingsphere.scaling.core.job.progress.JobProgress;
import org.apache.shardingsphere.scaling.core.util.JobConfigurationUtil;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.Map;
import java.util.Optional;
import java.util.Properties;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public final class ScalingAPIImplTest {
    
    private final ScalingAPI scalingAPI = ScalingAPIFactory.getScalingAPI();
    
    @BeforeClass
    public static void init() {
        EmbedTestingServer.start();
        ScalingContext.getInstance().init(mockServerConfig());
    }
    
    private static ServerConfiguration mockServerConfig() {
        ServerConfiguration result = new ServerConfiguration();
        result.setGovernanceConfig(new GovernanceConfiguration("test", new GovernanceCenterConfiguration("Zookeeper", EmbedTestingServer.getConnectionString(), new Properties()), true));
        return result;
    }
    
    @Test
    public void assertStartAndList() {
        Optional<Long> jobId = scalingAPI.start(JobConfigurationUtil.initJobConfig("/config.json"));
        assertTrue(jobId.isPresent());
        JobInfo jobInfo = getNonNullJobInfo(jobId.get());
        assertTrue(jobInfo.isActive());
        assertThat(jobInfo.getStatus(), is(JobStatus.RUNNING.name()));
        assertThat(jobInfo.getTables(), is(new String[]{"ds_0.t1", "ds_0.t2"}));
        assertThat(jobInfo.getShardingTotalCount(), is(2));
        assertThat(jobInfo.getInventoryFinishedPercentage(), is(0));
        assertThat(jobInfo.getIncrementalAverageDelayMilliseconds(), is(-1L));
    }
    
    private Optional<JobInfo> getJobInfo(final long jobId) {
        return scalingAPI.list().stream().filter(each -> each.getJobId() == jobId).reduce((a, b) -> a);
    }
    
    private JobInfo getNonNullJobInfo(final long jobId) {
        Optional<JobInfo> result = getJobInfo(jobId);
        assertTrue(result.isPresent());
        return result.get();
    }
    
    @Test
    public void assertStartOrStopById() {
        Optional<Long> jobId = scalingAPI.start(JobConfigurationUtil.initJobConfig("/config.json"));
        assertTrue(jobId.isPresent());
        assertTrue(getNonNullJobInfo(jobId.get()).isActive());
        scalingAPI.stop(jobId.get());
        assertFalse(getNonNullJobInfo(jobId.get()).isActive());
        scalingAPI.start(jobId.get());
        assertTrue(getNonNullJobInfo(jobId.get()).isActive());
    }
    
    @Test
    public void assertRemove() {
        Optional<Long> jobId = scalingAPI.start(JobConfigurationUtil.initJobConfig("/config.json"));
        assertTrue(jobId.isPresent());
        assertTrue(getJobInfo(jobId.get()).isPresent());
        scalingAPI.remove(jobId.get());
        assertFalse(getJobInfo(jobId.get()).isPresent());
    }
    
    @Test
    public void assertGetProgress() {
        Optional<Long> jobId = scalingAPI.start(JobConfigurationUtil.initJobConfig("/config.json"));
        assertTrue(jobId.isPresent());
        Map<Integer, JobProgress> jobProgressMap = scalingAPI.getProgress(jobId.get());
        assertThat(jobProgressMap.size(), is(2));
    }
}

@@ -854,16 +854,44 @@
 .impl;%0A%0A
+import lombok.SneakyThrows;%0A
 import o
@@ -1683,16 +1683,112 @@
 onUtil;%0A
+import org.apache.shardingsphere.scaling.core.util.ReflectionUtil;%0Aimport org.junit.AfterClass;%0A
 import o
@@ -2144,21 +2144,22 @@
 private 
-final
+static
  Scaling
@@ -2176,230 +2176,223 @@
 gAPI
- = ScalingAPIFactory.getScalingAPI();%0A    %0A    @BeforeClass%0A    public static void init() %7B%0A        EmbedTestingServer.start();%0A        ScalingContext.getInstance().init(mockServerConfig());%0A    %7D%0A    %0A    private static S
+;%0A    %0A    @BeforeClass%0A    @SneakyThrows(ReflectiveOperationException.class)%0A    public static void init() %7B%0A        EmbedTestingServer.start();%0A        ReflectionUtil.setFieldValue(ScalingContext.getInstance(), %22s
 erve
@@ -2398,23 +2398,18 @@
 erConfig
-uration
+%22,
  mockSer
@@ -2419,18 +2419,18 @@
 Config()
- %7B
+);
 %0A       
@@ -2434,272 +2434,54 @@
     
-ServerConfiguration result = new ServerConfiguration();%0A        result.setGovernanceConfig(new GovernanceConfiguration(%22test%22, new GovernanceCenterConfiguration(%22Zookeeper%22, EmbedTestingServer.getConnectionString(), new Properties()), true));%0A        return result
+scalingAPI = ScalingAPIFactory.getScalingAPI()
 ;%0A  
@@ -4666,10 +4666,564 @@
 ;%0A    %7D%0A
+    %0A    @AfterClass%0A    @SneakyThrows(ReflectiveOperationException.class)%0A    public static void afterClass() %7B%0A        ReflectionUtil.setFieldValue(ScalingContext.getInstance(), %22serverConfig%22, null);%0A    %7D%0A    %0A    private static ServerConfiguration mockServerConfig() %7B%0A        ServerConfiguration result = new ServerConfiguration();%0A        result.setGovernanceConfig(new GovernanceConfiguration(%22test%22, new GovernanceCenterConfiguration(%22Zookeeper%22, EmbedTestingServer.getConnectionString(), new Properties()), true));%0A        return result;%0A    %7D%0A
 %7D%0A

Optimize ScalingAPIImplTest (#9362)