/*
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.knox.gateway.service.config.remote;

import org.apache.commons.io.FileUtils;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.service.config.remote.config.RemoteConfigurationRegistriesAccessor;
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
import org.apache.knox.gateway.services.security.AliasService;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * An implementation of RemoteConfigurationRegistryClientService intended to be used for testing without having to
 * connect to an actual remote configuration registry.
 */
public class LocalFileSystemRemoteConfigurationRegistryClientService implements RemoteConfigurationRegistryClientService {

    public static final String TYPE = "LocalFileSystem";

    private Map<String, RemoteConfigurationRegistryClient> clients = new HashMap<>();


    @Override
    public void setAliasService(AliasService aliasService) {
        // N/A
    }

    @Override
    public RemoteConfigurationRegistryClient get(String name) {
        return clients.get(name);
    }

    @Override
    public void init(GatewayConfig config, Map<String, String> options) throws ServiceLifecycleException {
        List<RemoteConfigurationRegistryConfig> registryConfigurations =
                                        RemoteConfigurationRegistriesAccessor.getRemoteRegistryConfigurations(config);
        for (RemoteConfigurationRegistryConfig registryConfig : registryConfigurations) {
            if (TYPE.equalsIgnoreCase(registryConfig.getRegistryType())) {
                RemoteConfigurationRegistryClient registryClient = createClient(registryConfig);
                clients.put(registryConfig.getName(), registryClient);
            }
        }
    }

    @Override
    public void start() throws ServiceLifecycleException {
    }

    @Override
    public void stop() throws ServiceLifecycleException {
        for(RemoteConfigurationRegistryClient client : clients.values()) {
            try {
                client.close();
            } catch (Exception e) {
                throw new ServiceLifecycleException("failed to close client", e);
            }
        }
    }

    private RemoteConfigurationRegistryClient createClient(RemoteConfigurationRegistryConfig config) {
        String rootDir = config.getConnectionString();

        return new RemoteConfigurationRegistryClient() {
            @Override
            public void close() throws Exception {

            }

            private File root = new File(rootDir);

            @Override
            public String getAddress() {
                return root.getAbsolutePath();
            }

            @Override
            public boolean entryExists(String path) {
                return (new File(root, path)).exists();
            }

            @Override
            public List<EntryACL> getACL(String path) {
                List<EntryACL> result = new ArrayList<>();

                Path resolved = Paths.get(rootDir, path);
                try {
                    Map<String, List<String>> collected = new HashMap<>();

                    Set<PosixFilePermission> perms = Files.getPosixFilePermissions(resolved);
                    for (PosixFilePermission perm : perms) {
                        String[] parsed = perm.toString().split("_");
                        collected.computeIfAbsent(parsed[0].toLowerCase(Locale.ROOT), s -> new ArrayList<>()).add(parsed[1].toLowerCase(Locale.ROOT));
                    }

                    for (String id : collected.keySet()) {
                        EntryACL acl = new EntryACL() {
                            @Override
                            public String getId() {
                                return id;
                            }

                            @Override
                            public String getType() {
                                return "fs";
                            }

                            @Override
                            public Object getPermissions() {
                                return collected.get(id).toString();
                            }

                            @Override
                            public boolean canRead() {
                                return true;
                            }

                            @Override
                            public boolean canWrite() {
                                return true;
                            }
                        };
                        result.add(acl);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return result;
            }

            @Override
            public List<String> listChildEntries(String path) {
                List<String> result = new ArrayList<>();

                File entry = new File(root, path);
                if (entry.exists() && entry.isDirectory()) {
                    String[] list = entry.list();
                    if (list != null) {
                        result.addAll(Arrays.asList(entry.list()));
                    }
                }

                return result;
            }

            @Override
            public String getEntryData(String path) {
                return getEntryData(path, StandardCharsets.UTF_8.name());
            }

            @Override
            public String getEntryData(String path, String encoding) {
                String result = null;
                File entry = new File(root, path);
                if (entry.isFile() && entry.exists()) {
                    try {
                        result = FileUtils.readFileToString(entry, encoding);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return result;
            }

            @Override
            public void createEntry(String path) {
                createEntry(path, "");
            }

            @Override
            public void createEntry(String path, String data) {
                createEntry(path, data, StandardCharsets.UTF_8.name());
            }

            @Override
            public void createEntry(String path, String data, String encoding) {
                File entry = new File(root, path);
                if (!entry.exists()) {
                    if (data != null) {
                        try {
                            FileUtils.writeStringToFile(entry, data, encoding);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            @Override
            public int setEntryData(String path, String data) {
                setEntryData(path, data, StandardCharsets.UTF_8.name());
                return 0;
            }

            @Override
            public int setEntryData(String path, String data, String encoding) {
                File entry = new File(root, path);
                if (entry.exists()) {
                    try {
                        FileUtils.writeStringToFile(entry, data, encoding);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return 0;
            }

            @Override
            public boolean isAuthenticationConfigured() {
                return false;
            }

            @Override
            public void setACL(String path, List<EntryACL> acls) {
                //
            }

            @Override
            public void deleteEntry(String path) {
                File entry = new File(root, path);
                if (entry.exists()) {
                    entry.delete();
                }
            }

            @Override
            public void addChildEntryListener(String path, ChildEntryListener listener) throws Exception {
                // N/A
            }

            @Override
            public void addEntryListener(String path, EntryListener listener) throws Exception {
                // N/A
            }

            @Override
            public void removeEntryListener(String path) throws Exception {
                // N/A
            }
        };
    }

}
