// Copyright 2016 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.payments;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Handler;
import android.text.TextUtils;

import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.favicon.FaviconHelper;
import org.chromium.chrome.browser.payments.ui.LineItem;
import org.chromium.chrome.browser.payments.ui.PaymentInformation;
import org.chromium.chrome.browser.payments.ui.PaymentOption;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
import org.chromium.chrome.browser.payments.ui.SectionInformation;
import org.chromium.chrome.browser.preferences.PreferencesLauncher;
import org.chromium.chrome.browser.preferences.autofill.AutofillCreditCardEditor;
import org.chromium.chrome.browser.preferences.autofill.AutofillProfileEditor;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content_public.browser.WebContents;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojom.payments.PaymentDetails;
import org.chromium.mojom.payments.PaymentItem;
import org.chromium.mojom.payments.PaymentOptions;
import org.chromium.mojom.payments.PaymentRequest;
import org.chromium.mojom.payments.PaymentRequestClient;
import org.chromium.mojom.payments.PaymentResponse;
import org.chromium.mojom.payments.ShippingOption;
import org.chromium.ui.base.WindowAndroid;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Android implementation of the PaymentRequest service defined in
 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom.
 */
public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Client,
        PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback {
    /**
     * The size for the favicon in density-independent pixels.
     */
    private static final int FAVICON_SIZE_DP = 24;

    private static final String TAG = "cr_PaymentRequest";

    private final Handler mHandler = new Handler();

    private Activity mContext;
    private String mMerchantName;
    private String mOrigin;
    private Bitmap mFavicon;
    private List<PaymentApp> mApps;
    private PaymentRequestClient mClient;
    private Set<String> mSupportedMethods;
    private List<LineItem> mLineItems;
    private List<PaymentItem> mDisplayItems;
    private List<ShippingOption> mShippingOptions;
    private SectionInformation mShippingOptionsSection;
    private JSONObject mData;
    private SectionInformation mShippingAddressesSection;
    private List<PaymentApp> mPendingApps;
    private List<PaymentInstrument> mPendingInstruments;
    private SectionInformation mPaymentMethodsSection;
    private PaymentRequestUI mUI;
    private Callback<PaymentInformation> mPaymentInformationCallback;
    private Pattern mRegionCodePattern;
    private boolean mMerchantNeedsShippingAddress;

    /**
     * Builds the dialog.
     *
     * @param webContents The web contents that have invoked the PaymentRequest API.
     */
    public PaymentRequestImpl(WebContents webContents) {
        if (webContents == null) return;

        ContentViewCore contentViewCore = ContentViewCore.fromWebContents(webContents);
        if (contentViewCore == null) return;

        WindowAndroid window = contentViewCore.getWindowAndroid();
        if (window == null) return;

        mContext = window.getActivity().get();
        if (mContext == null) return;

        mMerchantName = webContents.getTitle();
        // The feature is available only in secure context, so it's OK to not show HTTPS.
        mOrigin = UrlUtilities.formatUrlForSecurityDisplay(webContents.getVisibleUrl(), false);

        final FaviconHelper faviconHelper = new FaviconHelper();
        float scale = mContext.getResources().getDisplayMetrics().density;
        faviconHelper.getLocalFaviconImageForURL(Profile.getLastUsedProfile(),
                webContents.getVisibleUrl(), (int) (FAVICON_SIZE_DP * scale + 0.5f),
                new FaviconHelper.FaviconImageCallback() {
                    @Override
                    public void onFaviconAvailable(Bitmap bitmap, String iconUrl) {
                        faviconHelper.destroy();
                        if (bitmap == null) return;
                        if (mUI == null) {
                            mFavicon = bitmap;
                            return;
                        }
                        mUI.setTitleBitmap(bitmap);
                    }
                });

        mApps = PaymentAppFactory.create(webContents);
        mRegionCodePattern = Pattern.compile(AutofillAddress.REGION_CODE_PATTERN);
    }

    /**
     * Called by the renderer to provide an endpoint for callbacks.
     */
    @Override
    public void setClient(PaymentRequestClient client) {
        assert mClient == null;

        mClient = client;

        if (mClient == null) return;

        if (mContext == null) {
            disconnectFromClientWithDebugMessage("Web contents don't have associated activity");
        }
    }

    /**
     * Called by the merchant website to show the payment request to the user.
     */
    @Override
    public void show(String[] supportedMethods, PaymentDetails details, PaymentOptions options,
            String stringifiedData) {
        if (mClient == null) return;

        if (mSupportedMethods != null) {
            disconnectFromClientWithDebugMessage("PaymentRequest.show() called more than once.");
            return;
        }

        mSupportedMethods = getValidatedSupportedMethods(supportedMethods);
        if (mSupportedMethods == null) {
            disconnectFromClientWithDebugMessage("Invalid payment methods");
            return;
        }

        if (!setLineItemsAndShippingOptionsOrDisconnectFromClient(details)) return;

        // If the merchant requests shipping and does not provide shipping options here, then the
        // merchant needs the shipping address to calculate shipping price and availability.
        boolean requestShipping = options != null && options.requestShipping;
        mMerchantNeedsShippingAddress = requestShipping && mShippingOptionsSection.isEmpty();

        mData = getValidatedData(mSupportedMethods, stringifiedData);
        if (mData == null) {
            disconnectFromClientWithDebugMessage("Invalid payment method specific data");
            return;
        }

        List<AutofillAddress> addresses = new ArrayList<>();
        List<AutofillProfile> profiles = PersonalDataManager.getInstance().getProfilesToSuggest();
        for (int i = 0; i < profiles.size(); i++) {
            AutofillProfile profile = profiles.get(i);
            if (profile.getCountryCode() != null
                    && mRegionCodePattern.matcher(profile.getCountryCode()).matches()
                    && profile.getStreetAddress() != null && profile.getRegion() != null
                    && profile.getLocality() != null && profile.getDependentLocality() != null
                    && profile.getPostalCode() != null && profile.getSortingCode() != null
                    && profile.getCompanyName() != null && profile.getFullName() != null) {
                addresses.add(new AutofillAddress(profile));
            }
        }

        int selectedIndex = SectionInformation.NO_SELECTION;
        if (!addresses.isEmpty() && mShippingOptionsSection.getSelectedItem() != null) {
            selectedIndex = 0;
        }
        mShippingAddressesSection = new SectionInformation(
                PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, selectedIndex, addresses);

        mPendingApps = new ArrayList<>(mApps);
        mPendingInstruments = new ArrayList<>();
        boolean isGettingInstruments = false;

        for (int i = 0; i < mApps.size(); i++) {
            PaymentApp app = mApps.get(i);
            Set<String> appMethods = app.getSupportedMethodNames();
            appMethods.retainAll(mSupportedMethods);
            if (appMethods.isEmpty()) {
                mPendingApps.remove(app);
            } else {
                isGettingInstruments = true;
                app.getInstruments(mDisplayItems, this);
            }
        }

        if (!isGettingInstruments) {
            mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PAYMENT_METHODS);
        }

        mUI = PaymentRequestUI.show(mContext, this, requestShipping, mMerchantName, mOrigin);
        if (mFavicon != null) mUI.setTitleBitmap(mFavicon);
        mFavicon = null;
    }

    /**
     * Called by merchant to update the shipping options and line items after the user has selected
     * their shipping address or shipping option.
     */
    @Override
    public void updateWith(PaymentDetails details) {
        if (mClient == null) return;

        if (mUI == null) {
            disconnectFromClientWithDebugMessage(
                    "PaymentRequestUpdateEvent.updateWith() called without PaymentRequest.show()");
            return;
        }

        if (!setLineItemsAndShippingOptionsOrDisconnectFromClient(details)) return;

        // Empty shipping options means the merchant cannot ship to the user's selected shipping
        // address.
        if (mShippingOptionsSection.isEmpty() && !mMerchantNeedsShippingAddress) {
            disconnectFromClientWithDebugMessage("Merchant indicates inablity to ship although "
                    + "originally indicated that can ship anywhere");
        }

        mUI.updateOrderSummarySection(mLineItems);
        mUI.updateSection(PaymentRequestUI.TYPE_SHIPPING_OPTIONS, mShippingOptionsSection);
    }

    private boolean setLineItemsAndShippingOptionsOrDisconnectFromClient(PaymentDetails details) {
        mLineItems = getValidatedLineItems(details);
        if (mLineItems == null) {
            disconnectFromClientWithDebugMessage("Invalid line items");
            return false;
        }
        mDisplayItems = Arrays.asList(details.displayItems);

        mShippingOptionsSection =
                getValidatedShippingOptions(details.displayItems[0].amount.currencyCode, details);
        if (mShippingOptionsSection == null) {
            disconnectFromClientWithDebugMessage("Invalid shipping options");
            return false;
        }
        mShippingOptions = Arrays.asList(details.shippingOptions);

        return true;
    }

    private HashSet<String> getValidatedSupportedMethods(String[] methods) {
        // Payment methods are required.
        if (methods == null || methods.length == 0) return null;

        HashSet<String> result = new HashSet<>();
        for (int i = 0; i < methods.length; i++) {
            // Payment methods should be non-empty.
            if (TextUtils.isEmpty(methods[i])) return null;
            result.add(methods[i]);
        }

        return result;
    }

    private List<LineItem> getValidatedLineItems(PaymentDetails details) {
        // Line items are required.
        if (details == null || details.displayItems == null || details.displayItems.length == 0) {
            return null;
        }

        for (int i = 0; i < details.displayItems.length; i++) {
            PaymentItem item = details.displayItems[i];
            // "id", "label", "currencyCode", and "value" should be non-empty.
            if (item == null || TextUtils.isEmpty(item.label) || item.amount == null
                    || TextUtils.isEmpty(item.amount.currencyCode)
                    || TextUtils.isEmpty(item.amount.value)) {
                return null;
            }
        }

        CurrencyStringFormatter formatter = new CurrencyStringFormatter(
                details.displayItems[0].amount.currencyCode, Locale.getDefault());

        // Currency codes should be in correct format.
        if (!formatter.isValidAmountCurrencyCode(details.displayItems[0].amount.currencyCode)) {
            return null;
        }

        List<LineItem> result = new ArrayList<>(details.displayItems.length);
        for (int i = 0; i < details.displayItems.length; i++) {
            PaymentItem item = details.displayItems[i];

            // All currency codes must match.
            if (!item.amount.currencyCode.equals(details.displayItems[0].amount.currencyCode)) {
                return null;
            }

            // Value should be in correct format.
            if (!formatter.isValidAmountValue(item.amount.value)) return null;

            result.add(new LineItem(item.label,
                    i == details.displayItems.length - 1 ? item.amount.currencyCode : "",
                    formatter.format(item.amount.value)));
        }

        return result;
    }

    private SectionInformation getValidatedShippingOptions(
            String itemsCurrencyCode, PaymentDetails details) {
        // Shipping options are optional.
        if (details.shippingOptions == null || details.shippingOptions.length == 0) {
            return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS);
        }

        CurrencyStringFormatter formatter =
                new CurrencyStringFormatter(itemsCurrencyCode, Locale.getDefault());

        for (int i = 0; i < details.shippingOptions.length; i++) {
            ShippingOption option = details.shippingOptions[i];

            // Each "id", "label", "currencyCode", and "value" should be non-empty.
            // Each "value" should be a valid amount value.
            // Each "currencyCode" should match the line items' currency codes.
            if (option == null || TextUtils.isEmpty(option.id) || TextUtils.isEmpty(option.label)
                    || option.amount == null || TextUtils.isEmpty(option.amount.currencyCode)
                    || TextUtils.isEmpty(option.amount.value)
                    || !itemsCurrencyCode.equals(option.amount.currencyCode)
                    || !formatter.isValidAmountValue(option.amount.value)) {
                return null;
            }
        }

        boolean isSameAsCurrentOptions = true;
        if (mShippingOptions == null || mShippingOptions.size() != details.shippingOptions.length) {
            isSameAsCurrentOptions = false;
        } else {
            for (int i = 0; i < details.shippingOptions.length; i++) {
                ShippingOption newOption = details.shippingOptions[i];
                ShippingOption currentOption = mShippingOptions.get(i);
                if (!newOption.id.equals(currentOption.id)
                        || !newOption.label.equals(currentOption.label)
                        || !newOption.amount.currencyCode.equals(currentOption.amount.currencyCode)
                        || !newOption.amount.value.equals(currentOption.amount.value)) {
                    isSameAsCurrentOptions = false;
                    break;
                }
            }
        }
        if (isSameAsCurrentOptions) return mShippingOptionsSection;

        List<PaymentOption> result = new ArrayList<>();
        for (int i = 0; i < details.shippingOptions.length; i++) {
            ShippingOption option = details.shippingOptions[i];
            result.add(new PaymentOption(option.id, option.label,
                    formatter.format(option.amount.value), PaymentOption.NO_ICON));
        }

        return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS,
                result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result);
    }

    private JSONObject getValidatedData(Set<String> supportedMethods, String stringifiedData) {
        if (TextUtils.isEmpty(stringifiedData)) return new JSONObject();

        JSONObject result;
        try {
            result = new JSONObject(stringifiedData);
        } catch (JSONException e) {
            // Payment method specific data should be a JSON object.
            return null;
        }

        Iterator<String> it = result.keys();
        while (it.hasNext()) {
            String name = it.next();
            // Each key should be one of the supported payment methods.
            if (!supportedMethods.contains(name)) return null;
            // Each value should be a JSON object.
            if (result.optJSONObject(name) == null) return null;
        }

        return result;
    }

    /**
     * Called to retrieve the data to show in the initial PaymentRequest UI.
     */
    @Override
    public void getDefaultPaymentInformation(Callback<PaymentInformation> callback) {
        mPaymentInformationCallback = callback;

        if (mPaymentMethodsSection == null) return;

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                provideDefaultPaymentInformation();
            }
        });
    }

    private void provideDefaultPaymentInformation() {
        mPaymentInformationCallback.onResult(new PaymentInformation(
                mLineItems.get(mLineItems.size() - 1), mShippingAddressesSection.getSelectedItem(),
                mShippingOptionsSection.getSelectedItem(),
                mPaymentMethodsSection.getSelectedItem()));
        mPaymentInformationCallback = null;
    }

    @Override
    public void getLineItems(final Callback<List<LineItem>> callback) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onResult(mLineItems);
            }
        });
    }

    @Override
    public void getSectionInformation(@PaymentRequestUI.DataType final int optionType,
            final Callback<SectionInformation> callback) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) {
                    callback.onResult(mShippingAddressesSection);
                } else if (optionType == PaymentRequestUI.TYPE_SHIPPING_OPTIONS) {
                    callback.onResult(mShippingOptionsSection);
                } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) {
                    assert mPaymentMethodsSection != null;
                    callback.onResult(mPaymentMethodsSection);
                }
            }
        });
    }

    @Override
    public void onSectionOptionChanged(
            @PaymentRequestUI.DataType int optionType, PaymentOption option) {
        if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) {
            // This may update the line items and/or the shipping options.
            assert option instanceof AutofillAddress;
            mShippingAddressesSection.setSelectedItem(option);
            if (mMerchantNeedsShippingAddress) {
                mClient.onShippingAddressChange(((AutofillAddress) option).toShippingAddress());
            }
        } else if (optionType == PaymentRequestUI.TYPE_SHIPPING_OPTIONS) {
            // This may update the line items.
            mShippingOptionsSection.setSelectedItem(option);
            mClient.onShippingOptionChange(option.getIdentifier());
        } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) {
            assert option instanceof PaymentInstrument;
            mPaymentMethodsSection.setSelectedItem(option);
        }
    }


    @Override
    public void onSectionAddOption(@PaymentRequestUI.DataType int optionType) {
        // TODO(rouslan, dfalcantara): Make this code do something more useful.
        if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) {
            PreferencesLauncher.launchSettingsPage(mContext, AutofillProfileEditor.class.getName());
        } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) {
            PreferencesLauncher.launchSettingsPage(
                    mContext, AutofillCreditCardEditor.class.getName());
        }
    }

    @Override
    public void onPayClicked(PaymentOption selectedShippingAddress,
            PaymentOption selectedShippingOption, PaymentOption selectedPaymentMethod) {
        assert selectedPaymentMethod instanceof PaymentInstrument;
        PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod;
        instrument.getDetails(mMerchantName, mOrigin, mDisplayItems,
                mData.optJSONObject(instrument.getMethodName()), this);
    }

    @Override
    public void onDismiss() {
        disconnectFromClientWithDebugMessage("Dialog dismissed");
        closeUI(false);
    }

    /**
     * Called by the merchant website to abort the payment.
     */
    @Override
    public void abort() {
        closeClient();
        closeUI(false);
    }

    /**
     * Called when the merchant website has processed the payment.
     */
    @Override
    public void complete(boolean success) {
        closeUI(success);
    }

    /**
     * Called when the renderer closes the Mojo connection.
     */
    @Override
    public void close() {
        closeClient();
        closeUI(false);
    }

    /**
     * Called when the Mojo connection encounters an error.
     */
    @Override
    public void onConnectionError(MojoException e) {
        closeClient();
        closeUI(false);
    }

    /**
     * Called after retrieving the list of payment instruments in an app.
     */
    @Override
    public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instruments) {
        mPendingApps.remove(app);

        if (instruments != null) {
            for (int i = 0; i < instruments.size(); i++) {
                PaymentInstrument instrument = instruments.get(i);
                if (mSupportedMethods.contains(instrument.getMethodName())) {
                    mPendingInstruments.add(instrument);
                } else {
                    instrument.dismiss();
                }
            }
        }

        if (mPendingApps.isEmpty()) {
            mPaymentMethodsSection = new SectionInformation(
                    PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstruments);
            mPendingInstruments.clear();

            if (mPaymentInformationCallback != null) provideDefaultPaymentInformation();
        }
    }

    /**
     * Called after retrieving instrument details.
     */
    @Override
    public void onInstrumentDetailsReady(String methodName, String stringifiedDetails) {
        PaymentResponse response = new PaymentResponse();
        response.methodName = methodName;
        response.stringifiedDetails = stringifiedDetails;

        PaymentOption selectedShippingAddress = mShippingAddressesSection.getSelectedItem();
        if (selectedShippingAddress != null) {
            // Shipping addresses are created in show(). The should all be instances of
            // AutofillAddress.
            assert selectedShippingAddress instanceof AutofillAddress;
            response.shippingAddress =
                    ((AutofillAddress) selectedShippingAddress).toShippingAddress();
        }

        PaymentOption selectedShippingOption = mShippingOptionsSection.getSelectedItem();
        if (selectedShippingOption != null && selectedShippingOption.getIdentifier() != null) {
            response.shippingOptionId = selectedShippingOption.getIdentifier();
        }

        mClient.onPaymentResponse(response);
    }

    /**
     * Called if unable to retrieve instrument details.
     */
    @Override
    public void onInstrumentDetailsError() {
        disconnectFromClientWithDebugMessage("Failed to retrieve payment instrument details");
        closeUI(false);
    }

    private void disconnectFromClientWithDebugMessage(String debugMessage) {
        Log.d(TAG, debugMessage);
        mClient.onError();
        closeClient();
    }

    /**
     * Closes the UI. If the client is still connected, then it's notified of UI hiding.
     */
    private void closeUI(boolean paymentSuccess) {
        if (mUI != null) {
            mUI.close(paymentSuccess, new Runnable() {
                @Override
                public void run() {
                    if (mClient != null) mClient.onComplete();
                    closeClient();
                }
            });
            mUI = null;
        }

        if (mPaymentMethodsSection != null) {
            for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) {
                PaymentOption option = mPaymentMethodsSection.getItem(i);
                assert option instanceof PaymentInstrument;
                ((PaymentInstrument) option).dismiss();
            }
            mPaymentMethodsSection = null;
        }
    }

    private void closeClient() {
        if (mClient != null) mClient.close();
        mClient = null;
    }
}
