/*
       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.cordova.file;

import android.net.Uri;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;

import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public abstract class Filesystem {

    protected final Uri rootUri;
    protected final CordovaResourceApi resourceApi;
    protected final CordovaPreferences preferences;
    public final String name;
    private JSONObject rootEntry;

    static String SCHEME_HTTPS = "https";
    static String DEFAULT_HOSTNAME = "localhost";

    public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi, CordovaPreferences preferences) {
        this.rootUri = rootUri;
        this.name = name;
        this.resourceApi = resourceApi;
        this.preferences = preferences;
    }

    public interface ReadFileCallback {
        public void handleData(InputStream inputStream, String contentType) throws IOException;
    }

    public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
        try {
            String path = inputURL.path;
            int end = path.endsWith("/") ? 1 : 0;
            String[] parts = path.substring(0, path.length() - end).split("/+");
            String fileName = parts[parts.length - 1];

            JSONObject entry = new JSONObject();
            entry.put("isFile", !inputURL.isDirectory);
            entry.put("isDirectory", inputURL.isDirectory);
            entry.put("name", fileName);
            entry.put("fullPath", path);
            // The file system can't be specified, as it would lead to an infinite loop,
            // but the filesystem name can be.
            entry.put("filesystemName", inputURL.fsName);
            // Backwards compatibility
            entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);

            String nativeUrlStr = nativeURL.toString();
            if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
                nativeUrlStr += "/";
            }
            entry.put("nativeURL", nativeUrlStr);
            return entry;
        } catch (JSONException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
        Uri nativeUri = toNativeUri(inputURL);
        return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
    }

    public JSONObject makeEntryForNativeUri(Uri nativeUri) {
        LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
        return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
    }

    public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
        return makeEntryForURL(inputURL);
    }

    public JSONObject makeEntryForFile(File file) {
        return makeEntryForNativeUri(Uri.fromFile(file));
    }

    abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
            JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;

    abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;

    abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;

    abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;

    public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
        LocalFilesystemURL[] children = listChildren(inputURL);
        JSONArray entries = new JSONArray();
        if (children != null) {
            for (LocalFilesystemURL url : children) {
                entries.put(makeEntryForURL(url));
            }
        }
        return entries;
    }

    abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;

    public Uri getRootUri() {
        return rootUri;
    }

    public boolean exists(LocalFilesystemURL inputURL) {
        try {
            getFileMetadataForLocalURL(inputURL);
        } catch (FileNotFoundException e) {
            return false;
        }
        return true;
    }

    public Uri nativeUriForFullPath(String fullPath) {
        Uri ret = null;
        if (fullPath != null) {
            String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
            if (encodedPath.startsWith("/")) {
                encodedPath = encodedPath.substring(1);
            }
            ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
        }
        return ret;
    }

    public LocalFilesystemURL localUrlforFullPath(String fullPath) {
        Uri nativeUri = nativeUriForFullPath(fullPath);
        if (nativeUri != null) {
            return toLocalUri(nativeUri);
        }
        return null;
    }

    /**
     * Removes multiple repeated //s, and collapses processes ../s.
     */
    protected static String normalizePath(String rawPath) {
        // If this is an absolute path, trim the leading "/" and replace it later
        boolean isAbsolutePath = rawPath.startsWith("/");
        if (isAbsolutePath) {
            rawPath = rawPath.replaceFirst("/+", "");
        }
        ArrayList<String> components = new ArrayList<String>(Arrays.asList(rawPath.split("/+")));
        for (int index = 0; index < components.size(); ++index) {
            if (components.get(index).equals("..")) {
                components.remove(index);
                if (index > 0) {
                    components.remove(index-1);
                    --index;
                }
            }
        }
        StringBuilder normalizedPath = new StringBuilder();
        for(String component: components) {
            normalizedPath.append("/");
            normalizedPath.append(component);
        }
        if (isAbsolutePath) {
            return normalizedPath.toString();
        } else {
            return normalizedPath.toString().substring(1);
        }
    }

    /**
     * Gets the free space in bytes available on this filesystem.
     * Subclasses may override this method to return nonzero free space.
     */
    public long getFreeSpaceInBytes() {
        return 0;
    }

    public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
    public abstract LocalFilesystemURL toLocalUri(Uri inputURL);

    public JSONObject getRootEntry() {
        if (rootEntry == null) {
            rootEntry = makeEntryForNativeUri(rootUri);
        }
        return rootEntry;
    }

    public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
        Uri parentUri = inputURL.uri;
        String parentPath = new File(inputURL.uri.getPath()).getParent();
        if (!"/".equals(parentPath)) {
            parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
        }
        return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
    }

    protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
        // I know this looks weird but it is to work around a JSON bug.
        if ("null".equals(newName) || "".equals(newName)) {
            newName = srcURL.uri.getLastPathSegment();;
        }

        String newDest = destURL.uri.toString();
        if (newDest.endsWith("/")) {
            newDest = newDest + newName;
        } else {
            newDest = newDest + "/" + newName;
        }
        if (isDirectory) {
            newDest += '/';
        }
        return LocalFilesystemURL.parse(newDest);
    }

    /* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
     * the destination URL on this filesystem, optionally with a new filename.
     * If move is true, then this method should either perform an atomic move operation
     * or remove the source file when finished.
     */
    public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
            Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
        // First, check to see that we can do it
        if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
            throw new NoModificationAllowedException("Cannot move file at source URL");
        }
        final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);

        Uri srcNativeUri = srcFs.toNativeUri(srcURL);

        CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
        OutputStream os = null;
        try {
            os = getOutputStreamForURL(destination);
        } catch (IOException e) {
            ofrr.inputStream.close();
            throw e;
        }
        // Closes streams.
        resourceApi.copyResource(ofrr, os);

        if (move) {
            srcFs.removeFileAtLocalURL(srcURL);
        }
        return getEntryForLocalURL(destination);
    }

    public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
        return resourceApi.openOutputStream(toNativeUri(inputURL));
    }

    public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
                              ReadFileCallback readFileCallback) throws IOException {
        CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
        if (end < 0) {
            end = ofrr.length;
        }
        long numBytesToRead = end - start;
        try {
            if (start > 0) {
                ofrr.inputStream.skip(start);
            }
            InputStream inputStream = ofrr.inputStream;
            if (end < ofrr.length) {
                inputStream = new LimitedInputStream(inputStream, numBytesToRead);
            }
            readFileCallback.handleData(inputStream, ofrr.mimeType);
        } finally {
            ofrr.inputStream.close();
        }
    }

    abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
            boolean isBinary) throws NoModificationAllowedException, IOException;

    abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
            throws IOException, NoModificationAllowedException;

    // This method should return null if filesystem urls cannot be mapped to paths
    abstract String filesystemPathForURL(LocalFilesystemURL url);

    abstract LocalFilesystemURL URLforFilesystemPath(String path);

    abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);

    protected class LimitedInputStream extends FilterInputStream {
        long numBytesToRead;
        public LimitedInputStream(InputStream in, long numBytesToRead) {
            super(in);
            this.numBytesToRead = numBytesToRead;
        }
        @Override
        public int read() throws IOException {
            if (numBytesToRead <= 0) {
                return -1;
            }
            numBytesToRead--;
            return in.read();
        }
        @Override
        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
            if (numBytesToRead <= 0) {
                return -1;
            }
            int bytesToRead = byteCount;
            if (byteCount > numBytesToRead) {
                bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
            }
            int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
            numBytesToRead -= numBytesRead;
            return numBytesRead;
        }
    }

    protected Uri.Builder createLocalUriBuilder() {
        String scheme = preferences.getString("scheme", SCHEME_HTTPS).toLowerCase();
        String hostname = preferences.getString("hostname", DEFAULT_HOSTNAME).toLowerCase();
        String path = LocalFilesystemURL.fsNameToCdvKeyword(name);

        return new Uri.Builder()
            .scheme(scheme)
            .authority(hostname)
            .path(path);
    }
}
