/*
 * 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 com.epam.datalab.properties;

import com.epam.datalab.exceptions.DynamicChangePropertiesException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.epam.datalab.properties.ChangePropertiesConst.DEFAULT_NAME_PLACE;
import static com.epam.datalab.properties.ChangePropertiesConst.DEFAULT_VALUE_PLACE;

@Slf4j
public class ChangePropertiesService {

    public String readFileAsString(String selfServicePropPath, String serviceName) {
        try {
            log.info("Trying to read {}, file from path {} :", serviceName, selfServicePropPath);
            String currentConf = FileUtils.readFileToString(new File(selfServicePropPath), Charset.defaultCharset());
            return hideSecretsAndRemoveLicence(currentConf);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new DynamicChangePropertiesException(String.format("Failed while read file %s", serviceName));
        }
    }


    public void writeFileFromString(String newPropFile, String serviceName, String servicePath) {
        try {
            changeCHMODE(serviceName, servicePath, ChangePropertiesConst.DEFAULT_CHMOD, ChangePropertiesConst.WRITE_CHMOD);
            String oldFile = readFile(serviceName, servicePath);
            BufferedWriter writer = new BufferedWriter(new FileWriter(servicePath));
            log.info("Trying to overwrite {}, file for path {} :", serviceName, servicePath);
            writer.write(addLicence());
            writer.write(checkAndReplaceSecretIfEmpty(newPropFile, oldFile));
            log.info("{} overwritten successfully", serviceName);
            writer.close();
            changeCHMODE(serviceName, servicePath, ChangePropertiesConst.WRITE_CHMOD, ChangePropertiesConst.DEFAULT_CHMOD);
        } catch (IOException e) {
            log.error("Failed to create writer with path {}", servicePath);
            throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
        }
    }

    private String readFile(String serviceName, String servicePath) {
        String oldFile;
        try {
            oldFile = FileUtils.readFileToString(new File(servicePath), Charset.defaultCharset());
        } catch (IOException e) {
            log.error("Failed to read with path {}", servicePath);
            throw new DynamicChangePropertiesException(String.format("Failed during overwriting %s", serviceName));
        }
        return oldFile;
    }

    public RestartAnswer restart(RestartForm restartForm) {
        try {
            boolean billing = restartForm.isBilling();
            boolean provserv = restartForm.isProvserv();
            boolean ui = restartForm.isUi();
            String shCommand = buildSHRestartCommand(billing, provserv, ui);
            log.info("Tying to restart ui: {}, provserv: {}, billing: {}, with command: {}", ui,
                    provserv, billing, shCommand);
            Runtime.getRuntime().exec(shCommand).waitFor();
            return RestartAnswer.builder()
                    .billingSuccess(billing)
                    .provservSuccess(provserv)
                    .endpoint(restartForm.getEndpoint())
                    .build();
        } catch (IOException | InterruptedException e) {
            log.error(e.getMessage());
            return RestartAnswer.builder()
                    .billingSuccess(false)
                    .provservSuccess(false)
                    .endpoint(restartForm.getEndpoint())
                    .build();
        }
    }


    private String hideSecretsAndRemoveLicence(String currentConf) {
        Matcher passMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(currentConf);
        Matcher userMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(currentConf);
        List<String> secretsAndUsers = new ArrayList<>();
        final String[] confWithReplacedSecretConf = {removeLicence(currentConf)};
        while (passMatcher.find()) {
            String[] secret = passMatcher.group().split(":");
            if (!(secret[DEFAULT_VALUE_PLACE].isEmpty() ||
                    secret[DEFAULT_VALUE_PLACE].trim().isEmpty())) {

                secretsAndUsers.add(secret[DEFAULT_NAME_PLACE] + ":" + secret[DEFAULT_VALUE_PLACE]);
            }
        }
        while (userMatcher.find()) {
            String[] user = userMatcher.group().split(":");
            if (!(user[DEFAULT_VALUE_PLACE].isEmpty() ||
                    user[DEFAULT_VALUE_PLACE].trim().isEmpty()))
                secretsAndUsers.add(user[DEFAULT_NAME_PLACE] + ":" + user[DEFAULT_VALUE_PLACE]);

        }
        secretsAndUsers.forEach(x -> {
            String toReplace = x.split(":")[DEFAULT_NAME_PLACE] + ":" + ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT;
            confWithReplacedSecretConf[0] = confWithReplacedSecretConf[0].replace(x, toReplace);
        });
        return confWithReplacedSecretConf[0];
    }

    private String removeLicence(String conf) {
        return conf.split(ChangePropertiesConst.LICENCE_REGEX)[conf.split(ChangePropertiesConst.LICENCE_REGEX).length - 1];
    }


    private void changeCHMODE(String serviceName, String path, String fromMode, String toMode) throws IOException {
        try {
            String command = String.format(ChangePropertiesConst.CHANGE_CHMOD_SH_COMMAND_FORMAT, toMode, path);
            log.info("Trying to change chmod for file {} {}->{}", serviceName, fromMode, toMode);
            log.info("Execute command: {}", command);
            Runtime.getRuntime().exec(command).waitFor();
        } catch (InterruptedException e) {
            log.error("Failed change chmod for file {} {}->{}", serviceName, fromMode, toMode);
        }
    }

    private String addLicence() {
        return ChangePropertiesConst.LICENCE;
    }

    private String checkAndReplaceSecretIfEmpty(String newPropFile, String oldProf) {
        Map<String, Queue<String>> emptySecretsAndUserNames = findEmptySecretAndNames(newPropFile);
        return emptySecretsAndUserNames.isEmpty() ? newPropFile : replaceOldSecret(newPropFile, oldProf, emptySecretsAndUserNames);
    }

    private String replaceOldSecret(String newPropFile, String oldProf, Map<String, Queue<String>> emptySecrets) {
        String fileWithReplacedEmptySecrets = newPropFile;
        Matcher oldPassMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(oldProf);
        Matcher oldUserMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(oldProf);

        while (oldPassMatcher.find()) {
            String[] s = oldPassMatcher.group().split(":");
            if (emptySecrets.containsKey(s[ChangePropertiesConst.DEFAULT_NAME_PLACE])) {

                String poll = emptySecrets.get(s[DEFAULT_NAME_PLACE]).poll();
                if (poll != null) {
                    poll = poll.replace("*", "\\*");
                    String old = oldPassMatcher.group();
                    old = old.replace("$", "\\$");
                    old = old.replaceFirst("\\{", "\\{");
                    old = old.replaceFirst("}", "\\}");
                    fileWithReplacedEmptySecrets = fileWithReplacedEmptySecrets.replaceFirst(poll, old);
                }
            }
        }
        while (oldUserMatcher.find()) {
            String[] s = oldUserMatcher.group().split(":");
            if (emptySecrets.containsKey(s[ChangePropertiesConst.DEFAULT_NAME_PLACE])) {
                String poll = emptySecrets.get(s[DEFAULT_NAME_PLACE]).poll();
                if (poll != null) {
                    poll = poll.replace("*", "\\*");
                    String old = oldUserMatcher.group();
                    old = old.replace("$", "\\$");
                    old = old.replace("{", "\\}");
                    old = old.replace("}", "\\}");
                    fileWithReplacedEmptySecrets = fileWithReplacedEmptySecrets.replaceFirst(poll, old);
                }
            }
        }
        return fileWithReplacedEmptySecrets;
    }

    private Map<String, Queue<String>> findEmptySecretAndNames(String newPropFile) {
        Matcher passMatcher = Pattern.compile(ChangePropertiesConst.SECRET_REGEX).matcher(newPropFile);
        Matcher userNameMatcher = Pattern.compile(ChangePropertiesConst.USER_REGEX).matcher(newPropFile);
        Map<String, Queue<String>> emptySecrets = new HashMap<>();
        while (passMatcher.find()) {
            String[] s = passMatcher.group().split(":");
            if (s[DEFAULT_VALUE_PLACE].equals(ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT)) {
                if (emptySecrets.get(s[DEFAULT_NAME_PLACE]) == null) {
                    Queue<String> values = new ArrayDeque<>();
                    values.add(passMatcher.group());
                    emptySecrets.put(s[ChangePropertiesConst.DEFAULT_NAME_PLACE], values);
                } else {
                    Queue<String> values = emptySecrets.get(s[DEFAULT_NAME_PLACE]);
                    values.add(passMatcher.group());
                }
            }
        }

        while (userNameMatcher.find()) {
            String[] s = userNameMatcher.group().split(":");
            if (s[DEFAULT_VALUE_PLACE].equals(ChangePropertiesConst.SECRET_REPLACEMENT_FORMAT)) {
                if (emptySecrets.get(s[DEFAULT_NAME_PLACE]) == null) {
                    Queue<String> values = new ArrayDeque<>();
                    values.add(userNameMatcher.group());
                    emptySecrets.put(s[ChangePropertiesConst.DEFAULT_NAME_PLACE], values);
                } else {
                    Queue<String> values = emptySecrets.get(s[DEFAULT_NAME_PLACE]);
                    values.add(userNameMatcher.group());
                }
            }
        }
        return emptySecrets;
    }

    private String buildSHRestartCommand(boolean billing, boolean provserv, boolean ui) {
        StringBuilder stringBuilder = new StringBuilder(ChangePropertiesConst.SUPERVISORCTL_RESTART_SH_COMMAND);
        if (billing) stringBuilder.append(ChangePropertiesConst.BILLING_SERVICE_SUPERVISORCTL_RUN_NAME);
        if (provserv) stringBuilder.append(ChangePropertiesConst.PROVISIONING_SERVICE_SUPERVISORCTL_RUN_NAME);
        if (ui) stringBuilder.append(ChangePropertiesConst.SELF_SERVICE_SUPERVISORCTL_RUN_NAME);
        return stringBuilder.toString();
    }

}
