/*
 * 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.lemenzo.files.inspector;

import static com.lemenzo.files.util.Material3Config.getRes;

import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.util.AttributeSet;
import android.widget.TextView;

import androidx.annotation.StringRes;

import com.lemenzo.files.R;
import com.lemenzo.files.base.DocumentInfo;
import com.lemenzo.files.base.Lookup;
import com.lemenzo.files.base.StubLookup;
import com.lemenzo.files.inspector.InspectorController.DebugDisplay;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Organizes and Displays the debug information about a file. This view
 * should only be made visible when build is debuggable and system policies
 * allow debug "stuff".
 */
public class DebugView extends TableView implements DebugDisplay {

    private final Context mContext;
    private final Resources mRes;
    private Lookup<String, Executor> mExecutors = new StubLookup<>();

    public DebugView(Context context) {
        this(context, null);
    }

    public DebugView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DebugView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mRes = context.getResources();
    }

    void init(Lookup<String, Executor> executors) {
        assert executors != null;
        mExecutors = executors;
    }

    @Override
    public void accept(DocumentInfo info) {
        setTitle(getRes(R.string.inspector_debug_section), true);

        put(getRes(R.string.debug_user_id), info.userId.toString());
        put(getRes(R.string.debug_content_uri), info.derivedUri.toString());
        put(getRes(R.string.debug_document_id), info.documentId);
        put(getRes(R.string.debug_raw_mimetype), info.mimeType);
        put(getRes(R.string.debug_stream_types), "-");
        put(getRes(R.string.debug_raw_size), NumberFormat.getInstance().format(info.size));
        put(getRes(R.string.debug_is_archive), info.isArchive());
        put(getRes(R.string.debug_is_blocked_from_tree), info.isBlockedFromTree());
        put(getRes(R.string.debug_is_container), info.isContainer());
        put(getRes(R.string.debug_is_partial), info.isPartial());
        put(getRes(R.string.debug_is_virtual), info.isVirtual());
        put(getRes(R.string.debug_supports_create), info.isCreateSupported());
        put(getRes(R.string.debug_supports_delete), info.isDeleteSupported());
        put(getRes(R.string.debug_supports_trash), info.isTrashSupported());
        put(getRes(R.string.debug_supports_restore_from_trash), info.isRestoreSupported());
        put(getRes(R.string.debug_supports_metadata), info.isMetadataSupported());
        put(getRes(R.string.debug_supports_move), info.isMoveSupported());
        put(getRes(R.string.debug_supports_remove), info.isRemoveSupported());
        put(getRes(R.string.debug_supports_rename), info.isRenameSupported());
        put(getRes(R.string.debug_supports_settings), info.isSettingsSupported());
        put(getRes(R.string.debug_supports_thumbnail), info.isThumbnailSupported());
        put(getRes(R.string.debug_supports_weblink), info.isWeblinkSupported());
        put(getRes(R.string.debug_supports_write), info.isWriteSupported());

        // Load Document stream types of the file. For virtual files, this should be
        // something other than the primary type of the file.
        Executor executor = mExecutors.lookup(info.derivedUri.getAuthority());
        if (executor != null) {
            new AsyncTask<Void, Void, String[]>() {
                @Override
                protected String[] doInBackground(Void... params) {
                    return mContext.getContentResolver().getStreamTypes(info.derivedUri, "*/*");
                }

                @Override
                protected void onPostExecute(String[] streamTypes) {
                    put(
                            getRes(R.string.debug_stream_types),
                            streamTypes != null ? Arrays.toString(streamTypes) : "[]");
                }
            }.executeOnExecutor(executor, (Void[]) null);
        }
    }

    @Override
    public void accept(Bundle metadata) {
        if (metadata == null) {
            return;
        }

        String[] types = metadata.getStringArray(DocumentsContract.METADATA_TYPES);
        if (types == null) {
            return;
        }

        for (String type : types) {
            dumpMetadata(type, metadata.getBundle(type));
        }
    }

    private void dumpMetadata(String type, Bundle bundle) {
        String title =
                mContext.getResources()
                        .getString(getRes(R.string.inspector_debug_metadata_section));
        putTitle(String.format(title, type), true);
        List<String> keys = new ArrayList<>(bundle.keySet());
        Collections.sort(keys);
        for (String key : keys) {
            put(key, String.valueOf(bundle.get(key)));
        }
    }

    private void put(@StringRes int key, boolean value) {
        KeyValueRow row = put(mRes.getString(key), String.valueOf(value));
        TextView valueView = ((TextView) row.findViewById(getRes(R.id.table_row_value)));
        valueView.setTextColor(value ? 0xFF006400 : 0xFF9A2020);
    }
}
