/**
 * Copyright (C) the original author or authors.
 *
 * Licensed 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 ninja.jdbc;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

public class NinjaDbHikariProvider implements Provider<NinjaDatasources> {

    private final NinjaDatasourceConfigs ninjaDatasourceConfigs;

    @Inject
    public NinjaDbHikariProvider(NinjaDatasourceConfigs ninjaDatasourceConfigs) {
        this.ninjaDatasourceConfigs = ninjaDatasourceConfigs;
    }

    @Singleton
    @Override
    public NinjaDatasources get() {

        List<NinjaDatasource> ninjaDatasources
                = ninjaDatasourceConfigs.getDatasources().stream().map(ninjaDatasourceConfig -> {

                    Properties properties = extractHikariProperties(ninjaDatasourceConfig.getProperties());
                    HikariConfig config = new HikariConfig(properties);

                    config.setDriverClassName(ninjaDatasourceConfig.getDriver());
                    config.setJdbcUrl(ninjaDatasourceConfig.getJdbcUrl());
                    config.setUsername(ninjaDatasourceConfig.getUsername());
                    config.setPassword(ninjaDatasourceConfig.getPassword());
                    

                    HikariDataSource dataSource = new HikariDataSource(config);

                    NinjaDatasource ninjaDatasource = new NinjaDatasource(
                            ninjaDatasourceConfig.getName(),
                            dataSource);

                    return ninjaDatasource;

                }).collect(Collectors.toList());

        return new NinjaDatasourcesImpl(ninjaDatasources);

    }
    
    // See all supported properties here: https://github.com/brettwooldridge/HikariCP
    private Properties extractHikariProperties(Map<String, String> allPropertiesOfThisDatasource) {
        
        Properties properties = new Properties();
        allPropertiesOfThisDatasource.forEach((key, value) -> {
            
            if (key.startsWith("hikari.")) {
            
                String newKey = key.split("hikari.")[1];
                properties.put(newKey, value);
            
            }

        });
        
        
        return properties;
    
    }

}

@@ -925,16 +925,48 @@
 lectors;
+%0Aimport ninja.lifecycle.Dispose;
 %0A%0Apublic
@@ -1099,16 +1099,68 @@
 Configs;
+%0A    private List%3CNinjaDatasource%3E ninjaDatasources;
 %0A%0A    @I
@@ -2079,17 +2079,23 @@
 aSource 
-d
+hikariD
 ataSourc
@@ -2127,16 +2127,17 @@
 config);
+ 
 %0A%0A      
@@ -2294,17 +2294,23 @@
         
-d
+hikariD
 ataSourc
@@ -2407,16 +2407,75 @@
 List());
+%0A        %0A        this.ninjaDatasources = ninjaDatasources;
 %0A%0A      
@@ -3108,16 +3108,16 @@
 erties;%0A
-
     %0A   
@@ -3118,12 +3118,280 @@
   %0A    %7D
+%0A    %0A    @Dispose%0A    public void shutdown() %7B%0A        for (NinjaDatasource ninjaDatasource : ninjaDatasources) %7B%0A            HikariDataSource hikariDataSource = (HikariDataSource) ninjaDatasource.getDataSource();%0A            hikariDataSource.close();%0A        %7D%0A    %7D
 %0A%0A%7D%0A

Make sure datasources are shut down properly