/*
 * 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.sshd.common.file.util;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.ProviderMismatchException;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.AbstractList;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;

public abstract class BasePath<T extends BasePath<T, FS>, FS extends BaseFileSystem<T>> implements Path {

    protected final String root;
    protected final ImmutableList<String> names;
    private final FS fileSystem;
    private String strValue;
    private int hashValue;

    public BasePath(FS fileSystem, String root, ImmutableList<String> names) {
        this.fileSystem = ValidateUtils.checkNotNull(fileSystem, "No file system provided");
        this.root = root;
        this.names = names;
    }

    @SuppressWarnings("unchecked")
    protected T asT() {
        return (T) this;
    }

    protected T create(String root, String... names) {
        return create(root, new ImmutableList<>(names));
    }

    protected T create(String root, Collection<String> names) {
        return create(root, new ImmutableList<>(names.toArray(new String[names.size()])));
    }

    protected T create(String root, ImmutableList<String> names) {
        return fileSystem.create(root, names);
    }

    @Override
    public FS getFileSystem() {
        return fileSystem;
    }

    @Override
    public boolean isAbsolute() {
        return root != null;
    }

    @Override
    public T getRoot() {
        if (isAbsolute()) {
            return create(root);
        }
        return null;
    }

    @Override
    public T getFileName() {
        if (!names.isEmpty()) {
            return create(null, names.get(names.size() - 1));
        }
        return null;
    }

    @Override
    public T getParent() {
        if (names.isEmpty() || ((names.size() == 1) && (root == null))) {
            return null;
        }
        return create(root, names.subList(0, names.size() - 1));
    }

    @Override
    public int getNameCount() {
        return names.size();
    }

    @Override
    public T getName(int index) {
        int maxIndex = getNameCount();
        if ((index < 0) || (index >= maxIndex)) {
            throw new IllegalArgumentException("Invalid name index " + index + " - not in range [0-" + maxIndex + "]");
        }
        return create(null, names.subList(index, index + 1));
    }

    @Override
    public T subpath(int beginIndex, int endIndex) {
        int maxIndex = getNameCount();
        if ((beginIndex < 0) || (beginIndex >= maxIndex) || (endIndex > maxIndex) || (beginIndex >= endIndex)) {
            throw new IllegalArgumentException("subpath(" + beginIndex + "," + endIndex + ") bad index range - allowed [0-" + maxIndex + "]");
        }
        return create(null, names.subList(beginIndex, endIndex));
    }

    protected boolean startsWith(List<?> list, List<?> other) {
        return list.size() >= other.size() && list.subList(0, other.size()).equals(other);
    }

    @Override
    public boolean startsWith(Path other) {
        T p1 = asT();
        T p2 = checkPath(other);
        return Objects.equals(p1.getFileSystem(), p2.getFileSystem())
                && Objects.equals(p1.root, p2.root)
                && startsWith(p1.names, p2.names);
    }

    @Override
    public boolean startsWith(String other) {
        return startsWith(getFileSystem().getPath(other));
    }

    protected boolean endsWith(List<?> list, List<?> other) {
        return other.size() <= list.size() && list.subList(list.size() - other.size(), list.size()).equals(other);
    }

    @Override
    public boolean endsWith(Path other) {
        T p1 = asT();
        T p2 = checkPath(other);
        if (p2.isAbsolute()) {
            return p1.compareTo(p2) == 0;
        }
        return endsWith(p1.names, p2.names);
    }

    @Override
    public boolean endsWith(String other) {
        return endsWith(getFileSystem().getPath(other));
    }

    protected boolean isNormal() {
        int count = getNameCount();
        if ((count == 0) || ((count == 1) && !isAbsolute())) {
            return true;
        }
        boolean foundNonParentName = isAbsolute(); // if there's a root, the path doesn't start with ..
        boolean normal = true;
        for (String name : names) {
            if (name.equals("..")) {
                if (foundNonParentName) {
                    normal = false;
                    break;
                }
            } else {
                if (name.equals(".")) {
                    normal = false;
                    break;
                }
                foundNonParentName = true;
            }
        }
        return normal;
    }

    @Override
    public T normalize() {
        if (isNormal()) {
            return asT();
        }

        Deque<String> newNames = new ArrayDeque<>();
        for (String name : names) {
            if (name.equals("..")) {
                String lastName = newNames.peekLast();
                if (lastName != null && !lastName.equals("..")) {
                    newNames.removeLast();
                } else if (!isAbsolute()) {
                    // if there's a root and we have an extra ".." that would go up above the root, ignore it
                    newNames.add(name);
                }
            } else if (!name.equals(".")) {
                newNames.add(name);
            }
        }

        return newNames.equals(names) ? asT() : create(root, newNames);
    }

    @Override
    public T resolve(Path other) {
        T p1 = asT();
        T p2 = checkPath(other);
        if (p2.isAbsolute()) {
            return p2;
        }
        if (p2.names.isEmpty()) {
            return p1;
        }
        String[] names = new String[p1.names.size() + p2.names.size()];
        int index = 0;
        for (String p : p1.names) {
            names[index++] = p;
        }
        for (String p : p2.names) {
            names[index++] = p;
        }
        return create(p1.root, names);
    }

    @Override
    public T resolve(String other) {
        return resolve(getFileSystem().getPath(other, GenericUtils.EMPTY_STRING_ARRAY));
    }

    @Override
    public Path resolveSibling(Path other) {
        ValidateUtils.checkNotNull(other, "Missing sibling path argument");
        T parent = getParent();
        return parent == null ? other : parent.resolve(other);
    }

    @Override
    public Path resolveSibling(String other) {
        return resolveSibling(getFileSystem().getPath(other, GenericUtils.EMPTY_STRING_ARRAY));
    }

    @Override
    public T relativize(Path other) {
        T p1 = asT();
        T p2 = checkPath(other);
        if (!Objects.equals(p1.getRoot(), p2.getRoot())) {
            throw new IllegalArgumentException("Paths have different roots: " + this + ", " + other);
        }
        if (p2.equals(p1)) {
            return create(null);
        }
        if (p1.root == null && p1.names.isEmpty()) {
            return p2;
        }
        // Common subsequence
        int sharedSubsequenceLength = 0;
        for (int i = 0; i < Math.min(p1.names.size(), p2.names.size()); i++) {
            if (p1.names.get(i).equals(p2.names.get(i))) {
                sharedSubsequenceLength++;
            } else {
                break;
            }
        }
        int extraNamesInThis = Math.max(0, p1.names.size() - sharedSubsequenceLength);
        List<String> extraNamesInOther = (p2.names.size() <= sharedSubsequenceLength)
                ? Collections.<String>emptyList()
                : p2.names.subList(sharedSubsequenceLength, p2.names.size());
        List<String> parts = new ArrayList<>(extraNamesInThis + extraNamesInOther.size());
        // add .. for each extra name in this path
        parts.addAll(Collections.nCopies(extraNamesInThis, ".."));
        // add each extra name in the other path
        parts.addAll(extraNamesInOther);
        return create(null, parts);
    }

    @Override
    public T toAbsolutePath() {
        if (isAbsolute()) {
            return asT();
        }
        return fileSystem.getDefaultDir().resolve(this);
    }

    @Override
    public URI toUri() {
        File file = toFile();
        return file.toURI();
    }

    @Override
    public File toFile() {
        throw new UnsupportedOperationException("To file " + toAbsolutePath() + " N/A");
    }

    @Override
    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) throws IOException {
        return register(watcher, events, (WatchEvent.Modifier[]) null);
    }

    @Override
    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException {
        throw new UnsupportedOperationException("Register to watch " + toAbsolutePath() + " N/A");
    }

    @Override
    public Iterator<Path> iterator() {
        return new AbstractList<Path>() {
            @Override
            public Path get(int index) {
                return getName(index);
            }

            @Override
            public int size() {
                return getNameCount();
            }
        }.iterator();
    }

    @Override
    public int compareTo(Path paramPath) {
        T p1 = asT();
        T p2 = checkPath(paramPath);
        int c = compare(p1.root, p2.root);
        if (c != 0) {
            return c;
        }
        for (int i = 0; i < Math.min(p1.names.size(), p2.names.size()); i++) {
            String n1 = p1.names.get(i);
            String n2 = p2.names.get(i);
            c = compare(n1, n2);
            if (c != 0) {
                return c;
            }
        }
        return p1.names.size() - p2.names.size();
    }

    protected int compare(String s1, String s2) {
        if (s1 == null) {
            return s2 == null ? 0 : -1;
        } else {
            return s2 == null ? +1 : s1.compareTo(s2);
        }
    }

    @SuppressWarnings("unchecked")
    protected T checkPath(Path paramPath) {
        ValidateUtils.checkNotNull(paramPath, "Missing path argument");
        if (paramPath.getClass() != getClass()) {
            throw new ProviderMismatchException("Path is not of this class: " + paramPath + "[" + paramPath.getClass().getSimpleName() + "]");
        }
        T t = (T) paramPath;

        FileSystem fs = t.getFileSystem();
        if (fs.provider() != this.fileSystem.provider()) {
            throw new ProviderMismatchException("Mismatched providers for " + t);
        }
        return t;
    }

    @Override
    public int hashCode() {
        synchronized (this) {
            if (hashValue == 0) {
                hashValue = calculatedHashCode();
                if (hashValue == 0) {
                    hashValue = 1;
                }
            }
        }

        return hashValue;
    }

    protected int calculatedHashCode() {
        return Objects.hash(getFileSystem(), root, names);
    }

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof Path) && (compareTo((Path) obj) == 0);
    }

    @Override
    public String toString() {
        synchronized (this) {
            if (strValue == null) {
                strValue = asString();
            }
        }

        return strValue;
    }

    protected String asString() {
        StringBuilder sb = new StringBuilder();
        if (root != null) {
            sb.append(root);
        }

        String separator = getFileSystem().getSeparator();
        for (String name : names) {
            if ((sb.length() > 0) && (sb.charAt(sb.length() - 1) != '/')) {
                sb.append(separator);
            }
            sb.append(name);
        }

        return sb.toString();
    }
}
