// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package com.getcapacitor;

import android.content.Context;
import android.content.res.AssetManager;
import android.net.Uri;
import android.util.TypedValue;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class AndroidProtocolHandler {

    private Context context;

    public AndroidProtocolHandler(Context context) {
        this.context = context;
    }

    public InputStream openAsset(String path) throws IOException {
        return context.getAssets().open(path, AssetManager.ACCESS_STREAMING);
    }

    public InputStream openResource(Uri uri) {
        assert uri.getPath() != null;
        // The path must be of the form ".../asset_type/asset_name.ext".
        List<String> pathSegments = uri.getPathSegments();
        String assetType = pathSegments.get(pathSegments.size() - 2);
        String assetName = pathSegments.get(pathSegments.size() - 1);

        // Drop the file extension.
        assetName = assetName.split("\\.")[0];
        try {
            // Use the application context for resolving the resource package name so that we do
            // not use the browser's own resources. Note that if 'context' here belongs to the
            // test suite, it does not have a separate application context. In that case we use
            // the original context object directly.
            if (context.getApplicationContext() != null) {
                context = context.getApplicationContext();
            }
            int fieldId = getFieldId(context, assetType, assetName);
            int valueType = getValueType(context, fieldId);
            if (valueType == TypedValue.TYPE_STRING) {
                return context.getResources().openRawResource(fieldId);
            } else {
                Logger.error("Asset not of type string: " + uri);
            }
        } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {
            Logger.error("Unable to open resource URL: " + uri, e);
        }
        return null;
    }

    private static int getFieldId(Context context, String assetType, String assetName)
        throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class<?> d = context.getClassLoader().loadClass(context.getPackageName() + ".R$" + assetType);
        java.lang.reflect.Field field = d.getField(assetName);
        return field.getInt(null);
    }

    public InputStream openFile(String filePath) throws IOException {
        String realPath = filePath.replace(Bridge.CAPACITOR_FILE_START, "");
        File localFile = new File(realPath);
        return new FileInputStream(localFile);
    }

    public InputStream openContentUrl(Uri uri) throws IOException {
        Integer port = uri.getPort();
        String baseUrl = uri.getScheme() + "://" + uri.getHost();
        if (port != -1) {
            baseUrl += ":" + port;
        }
        String realPath = uri.toString().replace(baseUrl + Bridge.CAPACITOR_CONTENT_START, "content:/");

        InputStream stream = null;
        try {
            stream = context.getContentResolver().openInputStream(Uri.parse(realPath));
        } catch (SecurityException e) {
            Logger.error("Unable to open content URL: " + uri, e);
        }
        return stream;
    }

    private static int getValueType(Context context, int fieldId) {
        TypedValue value = new TypedValue();
        context.getResources().getValue(fieldId, value, true);
        return value.type;
    }
}
