/*
 * Copyright (C) 2017 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.timezone.data;

import com.android.timezone.distro.DistroException;
import com.android.timezone.distro.DistroVersion;
import com.android.timezone.distro.TimeZoneDistro;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.AssetManager;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.provider.TimeZoneRulesDataContract;
import android.provider.TimeZoneRulesDataContract.Operation;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static android.content.res.AssetManager.ACCESS_STREAMING;

/**
 * A basic implementation of a time zone data provider that can be used by OEMs to implement
 * an APK asset-based solution for time zone updates.
 */
public final class TimeZoneRulesDataProvider extends ContentProvider {

    static final String TAG = "TimeZoneRulesDataProvider";

    private static final String METADATA_KEY_OPERATION = "android.timezoneprovider.OPERATION";

    private static final Set<String> KNOWN_COLUMN_NAMES;
    private static final Map<String, Class<?>> KNOWN_COLUMN_TYPES;

    static {
        Set<String> columnNames = new HashSet<>();
        columnNames.add(Operation.COLUMN_TYPE);
        columnNames.add(Operation.COLUMN_DISTRO_MAJOR_VERSION);
        columnNames.add(Operation.COLUMN_DISTRO_MINOR_VERSION);
        columnNames.add(Operation.COLUMN_RULES_VERSION);
        columnNames.add(Operation.COLUMN_REVISION);
        KNOWN_COLUMN_NAMES = Collections.unmodifiableSet(columnNames);

        Map<String, Class<?>> columnTypes = new HashMap<>();
        columnTypes.put(Operation.COLUMN_TYPE, String.class);
        columnTypes.put(Operation.COLUMN_DISTRO_MAJOR_VERSION, Integer.class);
        columnTypes.put(Operation.COLUMN_DISTRO_MINOR_VERSION, Integer.class);
        columnTypes.put(Operation.COLUMN_RULES_VERSION, String.class);
        columnTypes.put(Operation.COLUMN_REVISION, Integer.class);
        KNOWN_COLUMN_TYPES = Collections.unmodifiableMap(columnTypes);
    }

    private final Map<String, Object> mColumnData = new HashMap<>();

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

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        super.attachInfo(context, info);

        // The time zone update process should run as the system user exclusively as it's a
        // system feature, not user dependent.
        UserHandle currentUserHandle = android.os.Process.myUserHandle();
        if (!currentUserHandle.isSystem()) {
            throw new SecurityException("ContentProvider is supposed to run as the system user,"
                    + " instead user=" + currentUserHandle);
        }

        // Confirm our security
        if (!TimeZoneRulesDataContract.AUTHORITY.equals(info.authority)) {
            // The authority looked for by the time zone updater is fixed.
            throw new SecurityException(
                    "android:authorities must be \"" + TimeZoneRulesDataContract.AUTHORITY + "\"");
        }
        if (!info.grantUriPermissions) {
            throw new SecurityException("Provider must grant uri permissions");
        }
        if (!info.exported) {
            // The content provider is accessed directly so must be exported.
            throw new SecurityException("android:exported must be \"true\"");
        }
        if (info.pathPermissions != null || info.writePermission != null) {
            // Use readPermission only to implement permissions.
            throw new SecurityException("Use android:readPermission only");
        }
        if (!android.Manifest.permission.UPDATE_TIME_ZONE_RULES.equals(info.readPermission)) {
            // Writing is not supported.
            throw new SecurityException("android:readPermission must be set to \""
                    + android.Manifest.permission.UPDATE_TIME_ZONE_RULES
                    + "\" is: " + info.readPermission);
        }

        // info.metadata is not filled in by default. Must ask for it again.
        final ProviderInfo infoWithMetadata = context.getPackageManager()
                .resolveContentProvider(info.authority, PackageManager.GET_META_DATA);
        Bundle metaData = infoWithMetadata.metaData;
        if (metaData == null) {
            throw new SecurityException("meta-data must be set");
        }

        // Work out what the operation type is.
        String type;
        try {
            type = getMandatoryMetaDataString(metaData, METADATA_KEY_OPERATION);
            mColumnData.put(Operation.COLUMN_TYPE, type);
        } catch (IllegalArgumentException e) {
            throw new SecurityException(METADATA_KEY_OPERATION + " meta-data not set.");
        }

        // Fill in version information if this is an install operation.
        if (Operation.TYPE_INSTALL.equals(type)) {
            // Extract the version information from the distro.
            InputStream distroBytesInputStream;
            try {
                distroBytesInputStream = context.getAssets().open(TimeZoneDistro.FILE_NAME);
            } catch (IOException e) {
                throw new SecurityException(
                        "Unable to open asset: " + TimeZoneDistro.FILE_NAME, e);
            }
            TimeZoneDistro distro = new TimeZoneDistro(distroBytesInputStream);
            try {
                DistroVersion distroVersion = distro.getDistroVersion();
                mColumnData.put(Operation.COLUMN_DISTRO_MAJOR_VERSION,
                        distroVersion.formatMajorVersion);
                mColumnData.put(Operation.COLUMN_DISTRO_MINOR_VERSION,
                        distroVersion.formatMinorVersion);
                mColumnData.put(Operation.COLUMN_RULES_VERSION, distroVersion.rulesVersion);
                mColumnData.put(Operation.COLUMN_REVISION, distroVersion.revision);
            } catch (IOException | DistroException e) {
                throw new SecurityException("Invalid asset: " + TimeZoneDistro.FILE_NAME, e);
            }

        }
    }

    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        if (!Operation.CONTENT_URI.equals(uri)) {
            return null;
        }
        final List<String> projectionList = Arrays.asList(projection);
        if (projection != null && !KNOWN_COLUMN_NAMES.containsAll(projectionList)) {
            throw new UnsupportedOperationException(
                    "Only " + KNOWN_COLUMN_NAMES + " columns supported.");
        }

        return new AbstractCursor() {
            @Override
            public int getCount() {
                return 1;
            }

            @Override
            public String[] getColumnNames() {
                return projectionList.toArray(new String[0]);
            }

            @Override
            public int getType(int column) {
                String columnName = projectionList.get(column);
                Class<?> columnJavaType = KNOWN_COLUMN_TYPES.get(columnName);
                if (columnJavaType == String.class) {
                    return Cursor.FIELD_TYPE_STRING;
                } else if (columnJavaType == Integer.class) {
                    return Cursor.FIELD_TYPE_INTEGER;
                } else {
                    throw new UnsupportedOperationException(
                            "Unsupported type: " + columnJavaType + " for " + columnName);
                }
            }

            @Override
            public String getString(int column) {
                checkPosition();
                String columnName = projectionList.get(column);
                if (KNOWN_COLUMN_TYPES.get(columnName) != String.class) {
                    throw new UnsupportedOperationException();
                }
                return (String) mColumnData.get(columnName);
            }

            @Override
            public short getShort(int column) {
                checkPosition();
                throw new UnsupportedOperationException();
            }

            @Override
            public int getInt(int column) {
                checkPosition();
                String columnName = projectionList.get(column);
                if (KNOWN_COLUMN_TYPES.get(columnName) != Integer.class) {
                    throw new UnsupportedOperationException();
                }
                return (Integer) mColumnData.get(columnName);
            }

            @Override
            public long getLong(int column) {
                return getInt(column);
            }

            @Override
            public float getFloat(int column) {
                throw new UnsupportedOperationException();
            }

            @Override
            public double getDouble(int column) {
                checkPosition();
                throw new UnsupportedOperationException();
            }

            @Override
            public boolean isNull(int column) {
                checkPosition();
                return column != 0;
            }
        };
    }

    @Override
    public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
            throws FileNotFoundException {
        if (!Operation.CONTENT_URI.equals(uri)) {
            throw new FileNotFoundException("Unknown URI: " + uri);
        }
        if (!"r".equals(mode)) {
            throw new FileNotFoundException("Only read-only access supported.");
        }

        // We cannot return the asset ParcelFileDescriptor from
        // assets.openFd(name).getParcelFileDescriptor() here as the receiver in the reading
        // process gets a ParcelFileDescriptor pointing at the whole .apk. Instead, we extract
        // the asset file we want to storage then wrap that in a ParcelFileDescriptor.
        File distroFile = null;
        try {
            distroFile = File.createTempFile("distro", null, getContext().getFilesDir());

            AssetManager assets = getContext().getAssets();
            try (InputStream is = assets.open(TimeZoneDistro.FILE_NAME, ACCESS_STREAMING);
                 FileOutputStream fos = new FileOutputStream(distroFile, false /* append */)) {
                copy(is, fos);
            }

            return ParcelFileDescriptor.open(distroFile, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (IOException e) {
            throw new RuntimeException("Unable to copy distro asset file", e);
        } finally {
            if (distroFile != null) {
                // Even if we have an open file descriptor pointing at the file it should be safe to
                // delete because of normal Unix file behavior. Deleting here avoids leaking any
                // storage.
                distroFile.delete();
            }
        }
    }

    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection,
            @Nullable String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
            @Nullable String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    private static String getMandatoryMetaDataString(Bundle metaData, String key) {
        if (!metaData.containsKey(key)) {
            throw new SecurityException("No metadata with key " + key + " found.");
        }
        return metaData.getString(key);
    }

    /**
     * Copies all of the bytes from {@code in} to {@code out}. Neither stream is closed.
     */
    private static void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[8192];
        int c;
        while ((c = in.read(buffer)) != -1) {
            out.write(buffer, 0, c);
        }
    }
}
