// Copyright 2015 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 org.chromium.chrome.browser.webapps;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.UrlUtilities;
import org.chromium.chrome.browser.omnibox.LocationBarLayout;

import java.net.URI;

/**
 * Maintains a URL bar that is displayed above the webapp's content.
 * For security reasons, this bar will appear when a user navigates to a website that is not
 * considered the same as the one that was used to open a WebappActivity originally.
 * The URL bar will disappear again once the user navigates back to the original website.
 *
 * Example scenario:
 * 0) User opens a webapp for http://domain1.com.           URL bar is hidden
 * 1) User navigates to http://domain1.com/some.html        URL bar is hidden
 * 2) User navigates to http://domain2.com/                 URL bar is shown
 * 3) User navigates back to http://domain1.com/some.html   URL bar is hidden
 */
public class WebappUrlBar extends FrameLayout implements View.OnLayoutChangeListener {
    private static final String TAG = "WebappUrlBar";

    private final TextView mUrlBar;
    private final View mSeparator;
    private final SparseIntArray mIconResourceWidths;

    private String mCurrentlyDisplayedUrl;
    private int mCurrentIconResource;

    /**
     * Creates a WebappUrlBar.
     * @param context Context to grab resources from.
     */
    public WebappUrlBar(Context context, AttributeSet attrSet) {
        super(context, attrSet);
        mIconResourceWidths = new SparseIntArray();

        mUrlBar = new TextView(context);
        mUrlBar.setSingleLine(true);
        mUrlBar.setMovementMethod(ScrollingMovementMethod.getInstance());
        mUrlBar.setHorizontalFadingEdgeEnabled(true);
        mSeparator = new View(context);

        addView(mUrlBar,
                new FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
                        Gravity.CENTER));
        addView(mSeparator,
                new FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.BOTTOM));

        // Set the colors.
        mSeparator.setBackgroundColor(
                context.getResources().getColor(R.color.webapp_url_bar_separator));
        setBackgroundColor(context.getResources().getColor(R.color.webapp_url_bar_bg));

        // Listen for changes in the URL bar's size.
        mUrlBar.addOnLayoutChangeListener(this);
    }

    /**
     * Updates the URL bar for the current URL.
     * @param url URL to display.
     * @param securityLevel Security level of the Tab.
     */
    public void update(String url, int securityLevel) {
        URI uri = createURI(url);
        updateSecurityIcon(securityLevel);
        updateDisplayedUrl(url, uri);
    }

    /**
     * @return the security icon being displayed for the current URL.
     */
    @VisibleForTesting
    protected int getCurrentIconResourceForTests() {
        return mCurrentIconResource;
    }

    /**
     * @return the URL being displayed.
     */
    @VisibleForTesting
    protected CharSequence getDisplayedUrlForTests() {
        return mUrlBar.getText();
    }

    /**
     * Show the end of the URL rather than the beginning.
     */
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
            int oldTop, int oldRight, int oldBottom) {
        Layout layout = mUrlBar.getLayout();
        if (layout == null) return;

        // Android doesn't account for the compound Drawable in its width calculations, leading to
        // improper scrolling and even Android improperly placing the horizontal fade in its
        // TextView calculation.  Get around it by calculating that width manually: crbug.com/303908
        int urlBarWidth = mUrlBar.getWidth();
        int iconWidth =
                mCurrentIconResource == 0 ? 0 : mIconResourceWidths.get(mCurrentIconResource);
        int availableTextWidth = urlBarWidth - iconWidth;
        int desiredWidth = (int) Layout.getDesiredWidth(layout.getText(), layout.getPaint());

        if (desiredWidth > availableTextWidth) {
            mUrlBar.scrollTo(desiredWidth - availableTextWidth, 0);
        } else {
            mUrlBar.scrollTo(0, 0);
        }
    }

    private static URI createURI(String url) {
        // Get rid of spaces temporarily: crbug.com/298465
        // Get rid of the need for this hack eventually: crbug.com/296870
        url = url.replace(" ", "%20");

        try {
            return URI.create(url);
        } catch (IllegalArgumentException exception) {
            Log.e(TAG, "Failed to convert URI: ", exception);
            return null;
        }
    }

    private void updateSecurityIcon(int securityLevel) {
        mCurrentIconResource = LocationBarLayout.getSecurityIconResource(securityLevel, false);

        if (mCurrentIconResource != 0 && mIconResourceWidths.get(mCurrentIconResource, -1) == -1) {
            Drawable icon = ApiCompatibilityUtils.getDrawable(getResources(), mCurrentIconResource);
            mIconResourceWidths.put(mCurrentIconResource, icon.getIntrinsicWidth());
        }

        ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mUrlBar,
                mCurrentIconResource, 0, 0, 0);
    }

    private void updateDisplayedUrl(String originalUrl, URI uri) {
        boolean showScheme = mCurrentIconResource == 0;
        String displayUrl = originalUrl;
        if (uri != null) {
            String shortenedUrl = UrlUtilities.getOriginForDisplay(uri, showScheme);
            if (!TextUtils.isEmpty(shortenedUrl)) displayUrl = shortenedUrl;
        }

        mUrlBar.setText(displayUrl);
        if (!TextUtils.equals(mCurrentlyDisplayedUrl, displayUrl)) {
            mCurrentlyDisplayedUrl = displayUrl;
        }
    }
}

@@ -2248,32 +2248,85 @@
 ngleLine(true);%0A
+        mUrlBar.setGravity(Gravity.CENTER_VERTICAL);%0A
         mUrlBar.

fix url bar alignment when partially insecure website is displayed