/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 com.android.server.slice;

import android.annotation.NonNull;
import android.content.ContentResolver;
import android.net.Uri;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;

import com.android.server.slice.DirtyTracker.Persistable;
import com.android.server.slice.SlicePermissionManager.PkgUser;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class SliceClientPermissions implements DirtyTracker, Persistable {

    private static final String TAG = "SliceClientPermissions";

    static final String TAG_CLIENT = "client";
    private static final String TAG_AUTHORITY = "authority";
    private static final String TAG_PATH = "path";
    private static final String NAMESPACE = null;

    private static final String ATTR_PKG = "pkg";
    private static final String ATTR_AUTHORITY = "authority";
    private static final String ATTR_FULL_ACCESS = "fullAccess";

    private final PkgUser mPkg;
    // Keyed off (authority, userId) rather than the standard (pkg, userId)
    private final ArrayMap<PkgUser, SliceAuthority> mAuths = new ArrayMap<>();
    private final DirtyTracker mTracker;
    private boolean mHasFullAccess;

    public SliceClientPermissions(@NonNull PkgUser pkg, @NonNull DirtyTracker tracker) {
        mPkg = pkg;
        mTracker = tracker;
    }

    public PkgUser getPkg() {
        return mPkg;
    }

    public synchronized Collection<SliceAuthority> getAuthorities() {
        return new ArrayList<>(mAuths.values());
    }

    public synchronized SliceAuthority getOrCreateAuthority(PkgUser authority, PkgUser provider) {
        SliceAuthority ret = mAuths.get(authority);
        if (ret == null) {
            ret = new SliceAuthority(authority.getPkg(), provider, this);
            mAuths.put(authority, ret);
            onPersistableDirty(ret);
        }
        return ret;
    }

    public synchronized SliceAuthority getAuthority(PkgUser authority) {
        return mAuths.get(authority);
    }

    public boolean hasFullAccess() {
        return mHasFullAccess;
    }

    public void setHasFullAccess(boolean hasFullAccess) {
        if (mHasFullAccess == hasFullAccess) return;
        mHasFullAccess = hasFullAccess;
        mTracker.onPersistableDirty(this);
    }

    public void removeAuthority(String authority, int userId) {
        if (mAuths.remove(new PkgUser(authority, userId)) != null) {
            mTracker.onPersistableDirty(this);
        }
    }

    public synchronized boolean hasPermission(Uri uri, int userId) {
        if (!Objects.equals(ContentResolver.SCHEME_CONTENT, uri.getScheme())) return false;
        SliceAuthority authority = getAuthority(new PkgUser(uri.getAuthority(), userId));
        return authority != null && authority.hasPermission(uri.getPathSegments());
    }

    public void grantUri(Uri uri, PkgUser providerPkg) {
        SliceAuthority authority = getOrCreateAuthority(
                new PkgUser(uri.getAuthority(), providerPkg.getUserId()),
                providerPkg);
        authority.addPath(uri.getPathSegments());
    }

    public void revokeUri(Uri uri, PkgUser providerPkg) {
        SliceAuthority authority = getOrCreateAuthority(
                new PkgUser(uri.getAuthority(), providerPkg.getUserId()),
                providerPkg);
        authority.removePath(uri.getPathSegments());
    }

    public void clear() {
        if (!mHasFullAccess && mAuths.isEmpty()) return;
        mHasFullAccess = false;
        mAuths.clear();
        onPersistableDirty(this);
    }

    @Override
    public void onPersistableDirty(Persistable obj) {
        mTracker.onPersistableDirty(this);
    }

    @Override
    public String getFileName() {
        return getFileName(mPkg);
    }

    public synchronized void writeTo(XmlSerializer out) throws IOException {
        out.startTag(NAMESPACE, TAG_CLIENT);
        out.attribute(NAMESPACE, ATTR_PKG, mPkg.toString());
        out.attribute(NAMESPACE, ATTR_FULL_ACCESS, mHasFullAccess ? "1" : "0");

        final int N = mAuths.size();
        for (int i = 0; i < N; i++) {
            out.startTag(NAMESPACE, TAG_AUTHORITY);
            out.attribute(NAMESPACE, ATTR_AUTHORITY, mAuths.valueAt(i).mAuthority);
            out.attribute(NAMESPACE, ATTR_PKG, mAuths.valueAt(i).mPkg.toString());

            mAuths.valueAt(i).writeTo(out);

            out.endTag(NAMESPACE, TAG_AUTHORITY);
        }

        out.endTag(NAMESPACE, TAG_CLIENT);
    }

    public static SliceClientPermissions createFrom(XmlPullParser parser, DirtyTracker tracker)
            throws XmlPullParserException, IOException {
        // Get to the beginning of the provider.
        while (parser.getEventType() != XmlPullParser.START_TAG
                || !TAG_CLIENT.equals(parser.getName())) {
            parser.next();
        }
        int depth = parser.getDepth();
        PkgUser pkgUser = new PkgUser(parser.getAttributeValue(NAMESPACE, ATTR_PKG));
        SliceClientPermissions provider = new SliceClientPermissions(pkgUser, tracker);
        String fullAccess = parser.getAttributeValue(NAMESPACE, ATTR_FULL_ACCESS);
        if (fullAccess == null) {
            fullAccess = "0";
        }
        provider.mHasFullAccess = Integer.parseInt(fullAccess) != 0;
        parser.next();

        while (parser.getDepth() > depth) {
            if (parser.getEventType() == XmlPullParser.START_TAG
                    && TAG_AUTHORITY.equals(parser.getName())) {
                try {
                    PkgUser pkg = new PkgUser(parser.getAttributeValue(NAMESPACE, ATTR_PKG));
                    SliceAuthority authority = new SliceAuthority(
                            parser.getAttributeValue(NAMESPACE, ATTR_AUTHORITY), pkg, provider);
                    authority.readFrom(parser);
                    provider.mAuths.put(new PkgUser(authority.getAuthority(), pkg.getUserId()),
                            authority);
                } catch (IllegalArgumentException e) {
                    Slog.e(TAG, "Couldn't read PkgUser", e);
                }
            }

            parser.next();
        }
        return provider;
    }

    public static String getFileName(PkgUser pkg) {
        return String.format("client_%s", pkg.toString());
    }

    public static class SliceAuthority implements Persistable {
        public static final String DELIMITER = "/";
        private final String mAuthority;
        private final DirtyTracker mTracker;
        private final PkgUser mPkg;
        private final ArraySet<String[]> mPaths = new ArraySet<>();

        public SliceAuthority(String authority, PkgUser pkg, DirtyTracker tracker) {
            mAuthority = authority;
            mPkg = pkg;
            mTracker = tracker;
        }

        public String getAuthority() {
            return mAuthority;
        }

        public PkgUser getPkg() {
            return mPkg;
        }

        void addPath(List<String> path) {
            String[] pathSegs = path.toArray(new String[path.size()]);
            for (int i = mPaths.size() - 1; i >= 0; i--) {
                String[] existing = mPaths.valueAt(i);
                if (isPathPrefixMatch(existing, pathSegs)) {
                    // Nothing to add here.
                    return;
                }
                if (isPathPrefixMatch(pathSegs, existing)) {
                    mPaths.removeAt(i);
                }
            }
            mPaths.add(pathSegs);
            mTracker.onPersistableDirty(this);
        }

        void removePath(List<String> path) {
            boolean changed = false;
            String[] pathSegs = path.toArray(new String[path.size()]);
            for (int i = mPaths.size() - 1; i >= 0; i--) {
                String[] existing = mPaths.valueAt(i);
                if (isPathPrefixMatch(pathSegs, existing)) {
                    changed = true;
                    mPaths.removeAt(i);
                }
            }
            if (changed) {
                mTracker.onPersistableDirty(this);
            }
        }

        public synchronized Collection<String[]> getPaths() {
            return new ArraySet<>(mPaths);
        }

        public boolean hasPermission(List<String> path) {
            for (String[] p : mPaths) {
                if (isPathPrefixMatch(p, path.toArray(new String[path.size()]))) {
                    return true;
                }
            }
            return false;
        }

        private boolean isPathPrefixMatch(String[] prefix, String[] path) {
            final int prefixSize = prefix.length;
            if (path.length < prefixSize) return false;

            for (int i = 0; i < prefixSize; i++) {
                if (!Objects.equals(path[i], prefix[i])) {
                    return false;
                }
            }

            return true;
        }

        @Override
        public String getFileName() {
            return null;
        }

        public synchronized void writeTo(XmlSerializer out) throws IOException {
            final int N = mPaths.size();
            for (int i = 0; i < N; i++) {
                final String[] segments = mPaths.valueAt(i);
                if (segments != null) {
                    out.startTag(NAMESPACE, TAG_PATH);
                    out.text(encodeSegments(segments));
                    out.endTag(NAMESPACE, TAG_PATH);
                }
            }
        }

        public synchronized void readFrom(XmlPullParser parser)
                throws IOException, XmlPullParserException {
            parser.next();
            int depth = parser.getDepth();
            while (parser.getDepth() >= depth) {
                if (parser.getEventType() == XmlPullParser.START_TAG
                        && TAG_PATH.equals(parser.getName())) {
                    mPaths.add(decodeSegments(parser.nextText()));
                }
                parser.next();
            }
        }

        private String encodeSegments(String[] s) {
            String[] out = new String[s.length];
            for (int i = 0; i < s.length; i++) {
                out[i] = Uri.encode(s[i]);
            }
            return TextUtils.join(DELIMITER, out);
        }

        private String[] decodeSegments(String s) {
            String[] sets = s.split(DELIMITER, -1);
            for (int i = 0; i < sets.length; i++) {
                sets[i] = Uri.decode(sets[i]);
            }
            return sets;
        }

        /**
         * Only for testing, no deep equality of these are done normally.
         */
        @Override
        public boolean equals(Object obj) {
            if (!getClass().equals(obj != null ? obj.getClass() : null)) return false;
            SliceAuthority other = (SliceAuthority) obj;
            if (mPaths.size() != other.mPaths.size()) return false;
            ArrayList<String[]> p1 = new ArrayList<>(mPaths);
            ArrayList<String[]> p2 = new ArrayList<>(other.mPaths);
            p1.sort(Comparator.comparing(o -> TextUtils.join(",", o)));
            p2.sort(Comparator.comparing(o -> TextUtils.join(",", o)));
            for (int i = 0; i < p1.size(); i++) {
                String[] a1 = p1.get(i);
                String[] a2 = p2.get(i);
                if (a1.length != a2.length) return false;
                for (int j = 0; j < a1.length; j++) {
                    if (!Objects.equals(a1[j], a2[j])) return false;
                }
            }
            return Objects.equals(mAuthority, other.mAuthority)
                    && Objects.equals(mPkg, other.mPkg);
        }

        @Override
        public String toString() {
            return String.format("(%s, %s: %s)", mAuthority, mPkg.toString(), pathToString(mPaths));
        }

        private String pathToString(ArraySet<String[]> paths) {
            return TextUtils.join(", ", paths.stream().map(s -> TextUtils.join("/", s))
                    .collect(Collectors.toList()));
        }
    }
}
