/*
 * Copyright (C) 2016 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.example.android.commitcontent.app;

import android.support.v13.view.inputmethod.EditorInfoCompat;
import android.support.v13.view.inputmethod.InputConnectionCompat;
import android.support.v13.view.inputmethod.InputContentInfoCompat;

import android.app.Activity;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends Activity {
    private static final String INPUT_CONTENT_INFO_KEY = "COMMIT_CONTENT_INPUT_CONTENT_INFO";
    private static final String COMMIT_CONTENT_FLAGS_KEY = "COMMIT_CONTENT_FLAGS";

    private static String TAG = "CommitContentSupport";

    private WebView mWebView;
    private TextView mLabel;
    private TextView mContentUri;
    private TextView mLinkUri;
    private TextView mMimeTypes;
    private TextView mFlags;

    private InputContentInfoCompat mCurrentInputContentInfo;
    private int mCurrentFlags;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.commit_content);

        final LinearLayout layout =
                (LinearLayout) findViewById(R.id.commit_content_sample_edit_boxes);

        // This declares that the IME cannot commit any content with
        // InputConnectionCompat#commitContent().
        layout.addView(createEditTextWithContentMimeTypes(null));

        // This declares that the IME can commit contents with
        // InputConnectionCompat#commitContent() if they match "image/gif".
        layout.addView(createEditTextWithContentMimeTypes(new String[]{"image/gif"}));

        // This declares that the IME can commit contents with
        // InputConnectionCompat#commitContent() if they match "image/png".
        layout.addView(createEditTextWithContentMimeTypes(new String[]{"image/png"}));

        // This declares that the IME can commit contents with
        // InputConnectionCompat#commitContent() if they match "image/jpeg".
        layout.addView(createEditTextWithContentMimeTypes(new String[]{"image/jpeg"}));

        // This declares that the IME can commit contents with
        // InputConnectionCompat#commitContent() if they match "image/webp".
        layout.addView(createEditTextWithContentMimeTypes(new String[]{"image/webp"}));

        // This declares that the IME can commit contents with
        // InputConnectionCompat#commitContent() if they match "image/png", "image/gif",
        // "image/jpeg", or "image/webp".
        layout.addView(createEditTextWithContentMimeTypes(
                new String[]{"image/png", "image/gif", "image/jpeg", "image/webp"}));

        mWebView = (WebView) findViewById(R.id.commit_content_webview);
        mMimeTypes = (TextView) findViewById(R.id.text_commit_content_mime_types);
        mLabel = (TextView) findViewById(R.id.text_commit_content_label);
        mContentUri = (TextView) findViewById(R.id.text_commit_content_content_uri);
        mLinkUri = (TextView) findViewById(R.id.text_commit_content_link_uri);
        mFlags = (TextView) findViewById(R.id.text_commit_content_link_flags);

        if (savedInstanceState != null) {
            final InputContentInfoCompat previousInputContentInfo = InputContentInfoCompat.wrap(
                    savedInstanceState.getParcelable(INPUT_CONTENT_INFO_KEY));
            final int previousFlags = savedInstanceState.getInt(COMMIT_CONTENT_FLAGS_KEY);
            if (previousInputContentInfo != null) {
                onCommitContentInternal(previousInputContentInfo, previousFlags);
            }
        }
    }

    private boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags,
            Bundle opts, String[] contentMimeTypes) {
        // Clear the temporary permission (if any).  See below about why we do this here.
        try {
            if (mCurrentInputContentInfo != null) {
                mCurrentInputContentInfo.releasePermission();
            }
        } catch (Exception e) {
            Log.e(TAG, "InputContentInfoCompat#releasePermission() failed.", e);
        } finally {
            mCurrentInputContentInfo = null;
        }

        mWebView.loadUrl("about:blank");
        mMimeTypes.setText("");
        mContentUri.setText("");
        mLabel.setText("");
        mLinkUri.setText("");
        mFlags.setText("");

        boolean supported = false;
        for (final String mimeType : contentMimeTypes) {
            if (inputContentInfo.getDescription().hasMimeType(mimeType)) {
                supported = true;
                break;
            }
        }
        if (!supported) {
            return false;
        }

        return onCommitContentInternal(inputContentInfo, flags);
    }

    private boolean onCommitContentInternal(InputContentInfoCompat inputContentInfo, int flags) {
        if ((flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
            try {
                inputContentInfo.requestPermission();
            } catch (Exception e) {
                Log.e(TAG, "InputContentInfoCompat#requestPermission() failed.", e);
                return false;
            }
        }

        mMimeTypes.setText(
                Arrays.toString(inputContentInfo.getDescription().filterMimeTypes("*/*")));
        mContentUri.setText(inputContentInfo.getContentUri().toString());
        mLabel.setText(inputContentInfo.getDescription().getLabel());
        Uri linkUri = inputContentInfo.getLinkUri();
        mLinkUri.setText(linkUri != null ? linkUri.toString() : "null");
        mFlags.setText(flagsToString(flags));
        mWebView.loadUrl(inputContentInfo.getContentUri().toString());
        mWebView.setBackgroundColor(Color.TRANSPARENT);

        // Due to the asynchronous nature of WebView, it is a bit too early to call
        // inputContentInfo.releasePermission() here. Hence we call IC#releasePermission() when this
        // method is called next time.  Note that calling IC#releasePermission() is just to be a
        // good citizen. Even if we failed to call that method, the system would eventually revoke
        // the permission sometime after inputContentInfo object gets garbage-collected.
        mCurrentInputContentInfo = inputContentInfo;
        mCurrentFlags = flags;

        return true;
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        if (mCurrentInputContentInfo != null) {
            savedInstanceState.putParcelable(INPUT_CONTENT_INFO_KEY,
                    (Parcelable) mCurrentInputContentInfo.unwrap());
            savedInstanceState.putInt(COMMIT_CONTENT_FLAGS_KEY, mCurrentFlags);
        }
        mCurrentInputContentInfo = null;
        mCurrentFlags = 0;
        super.onSaveInstanceState(savedInstanceState);
    }

    /**
     * Creates a new instance of {@link EditText} that is configured to specify the given content
     * MIME types to EditorInfo#contentMimeTypes so that developers can locally test how the current
     * input method behaves for such content MIME types.
     *
     * @param contentMimeTypes A {@link String} array that indicates the supported content MIME
     *                         types
     * @return a new instance of {@link EditText}, which specifies EditorInfo#contentMimeTypes with
     * the given content MIME types
     */
    private EditText createEditTextWithContentMimeTypes(String[] contentMimeTypes) {
        final CharSequence hintText;
        final String[] mimeTypes;  // our own copy of contentMimeTypes.
        if (contentMimeTypes == null || contentMimeTypes.length == 0) {
            hintText = "MIME: []";
            mimeTypes = new String[0];
        } else {
            hintText = "MIME: " + Arrays.toString(contentMimeTypes);
            mimeTypes = Arrays.copyOf(contentMimeTypes, contentMimeTypes.length);
        }
        EditText exitText = new EditText(this) {
            @Override
            public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
                final InputConnection ic = super.onCreateInputConnection(editorInfo);
                EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes);
                final InputConnectionCompat.OnCommitContentListener callback =
                        new InputConnectionCompat.OnCommitContentListener() {
                            @Override
                            public boolean onCommitContent(InputContentInfoCompat inputContentInfo,
                                    int flags, Bundle opts) {
                                return MainActivity.this.onCommitContent(
                                        inputContentInfo, flags, opts, mimeTypes);
                            }
                        };
                return InputConnectionCompat.createWrapper(ic, editorInfo, callback);
            }
        };
        exitText.setHint(hintText);
        exitText.setTextColor(Color.WHITE);
        exitText.setHintTextColor(Color.WHITE);
        return exitText;
    }

    /**
     * Converts {@code flags} specified in {@link InputConnectionCompat#commitContent(
     * InputConnection, EditorInfo, InputContentInfoCompat, int, Bundle)} to a human readable
     * string.
     *
     * @param flags the 2nd parameter of
     *              {@link InputConnectionCompat#commitContent(InputConnection, EditorInfo,
     *              InputContentInfoCompat, int, Bundle)}
     * @return a human readable string that corresponds to the given {@code flags}
     */
    private static String flagsToString(int flags) {
        final ArrayList<String> tokens = new ArrayList<>();
        if ((flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
            tokens.add("INPUT_CONTENT_GRANT_READ_URI_PERMISSION");
            flags &= ~InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
        }
        if (flags != 0) {
            tokens.add("0x" + Integer.toHexString(flags));
        }
        return TextUtils.join(" | ", tokens);
    }

}
