/*
 * 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.shardingjdbc.orchestration.spring.boot.type;

import lombok.SneakyThrows;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.shardingsphere.api.config.encrypt.EncryptRuleConfiguration;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.EncryptDataSource;
import org.apache.shardingsphere.shardingjdbc.orchestration.internal.datasource.OrchestrationEncryptDataSource;
import org.apache.shardingsphere.shardingjdbc.orchestration.spring.boot.registry.TestRegistryCenter;
import org.apache.shardingsphere.shardingjdbc.orchestration.spring.boot.util.EmbedTestingServer;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.lang.reflect.Field;

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

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = OrchestrationSpringBootRegistryEncryptTest.class)
@SpringBootApplication
@ActiveProfiles("registry")
public class OrchestrationSpringBootRegistryEncryptTest {
    
    @Resource
    private DataSource dataSource;
    
    @BeforeClass
    public static void init() {
        EmbedTestingServer.start();
        TestRegistryCenter testRegistryCenter = new TestRegistryCenter();
        testRegistryCenter.persist("/demo_spring_boot_ds_registry/config/schema/logic_db/datasource", "dataSource: !!org.apache.shardingsphere.orchestration.yaml.config.YamlDataSourceConfiguration\n"
            + "  dataSourceClassName: org.apache.commons.dbcp2.BasicDataSource\n"
            + "  properties:\n"
            + "    url: jdbc:h2:mem:ds;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL\n"
            + "    maxTotal: 100\n"
            + "    password: ''\n"
            + "    username: sa\n");
        testRegistryCenter.persist("/demo_spring_boot_ds_registry/config/schema/logic_db/rule", "encryptors:\n"
            + "  order_encrypt:\n"
            + "    assistedQueryColumns: ''\n"
            + "    props:\n"
            + "      aes.key.value: '123456'\n"
            + "    qualifiedColumns: t_order.user_id\n"
            + "    type: aes\n");
        testRegistryCenter.persist("/demo_spring_boot_ds_registry/config/props", "sql.show: 'true'\n");
        testRegistryCenter.persist("/demo_spring_boot_ds_registry/state/datasources", "");
    }
    
    @Test
    @SneakyThrows
    public void assertWithEncryptDataSource() {
        assertTrue(dataSource instanceof OrchestrationEncryptDataSource);
        Field field = OrchestrationEncryptDataSource.class.getDeclaredField("dataSource");
        field.setAccessible(true);
        EncryptDataSource encryptDataSource = (EncryptDataSource) field.get(dataSource);
        BasicDataSource embedDataSource = (BasicDataSource) encryptDataSource.getDataSource();
        assertThat(embedDataSource.getMaxTotal(), is(100));
        assertThat(embedDataSource.getUsername(), is("sa"));
        EncryptRuleConfiguration encryptRuleConfig = encryptDataSource.getEncryptRule().getEncryptRuleConfig();
        assertThat(encryptRuleConfig.getEncryptors().size(), is(1));
        assertTrue(encryptRuleConfig.getEncryptors().containsKey("order_encrypt"));
        assertThat(encryptRuleConfig.getEncryptors().get("order_encrypt").getType(), is("aes"));
    }
}

@@ -3129,59 +3129,181 @@
     
-assistedQueryColumns: ''%5Cn%22%0A            + %22    prop
+props:%5Cn%22%0A            + %22      aes.key.value: '123456'%5Cn%22%0A            + %22    type: aes%5Cn%22 %0A            + %22tables:%5Cn%22 %0A            + %22  t_order:%5Cn%22 %0A            + %22    column
 s:%5Cn
@@ -3325,39 +3325,25 @@
  %22      
-aes.key.value: '123456'
+ user_id:
 %5Cn%22%0A    
@@ -3361,34 +3361,27 @@
     
-qualified
+     cipher
 Column
-s
 : 
-t_order.
 user
@@ -3406,25 +3406,45 @@
  + %22    
-type: aes
+     encryptor: order_encrypt
 %5Cn%22);%0A  

modify init()