/*
 * Copyright 2014 OpenMarket Ltd
 * Copyright 2017 Vector Creations Ltd
 * Copyright 2018 New Vector Ltd
 *
 * 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 org.matrix.androidsdk.rest.client;

import org.matrix.androidsdk.HomeServerConnectionConfig;
import org.matrix.androidsdk.RestClient;
import org.matrix.androidsdk.core.JsonUtils;
import org.matrix.androidsdk.core.callback.ApiCallback;
import org.matrix.androidsdk.core.callback.SimpleApiCallback;
import org.matrix.androidsdk.core.model.MatrixError;
import org.matrix.androidsdk.rest.api.ThirdPidApi;
import org.matrix.androidsdk.rest.callback.RestAdapterCallback;
import org.matrix.androidsdk.rest.model.BulkLookupParams;
import org.matrix.androidsdk.rest.model.BulkLookupResponse;
import org.matrix.androidsdk.rest.model.SuccessResult;
import org.matrix.androidsdk.rest.model.pid.PidResponse;

import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// FIXME Stop sending the matrix token for this request...
public class ThirdPidRestClient extends RestClient<ThirdPidApi> {

    /**
     * {@inheritDoc}
     */
    public ThirdPidRestClient(HomeServerConnectionConfig hsConfig) {
        super(hsConfig, ThirdPidApi.class, "", false, true);
    }

    /**
     * Retrieve user matrix id from a 3rd party id.
     *
     * @param address  3rd party id
     * @param medium   the media.
     * @param callback the 3rd party callback
     */
    public void lookup3Pid(String address, String medium, final ApiCallback<String> callback) {
        mApi.lookup3PidV2(address, medium)
                .enqueue(new RestAdapterCallback<>("lookup3Pid",
                        null,
                        new SimpleApiCallback<PidResponse>(callback) {
                            @Override
                            public void onSuccess(PidResponse info) {
                                callback.onSuccess((null == info.mxid) ? "" : info.mxid);
                            }

                            @Override
                            public void onMatrixError(MatrixError e) {
                                if (e.mStatus == HttpURLConnection.HTTP_NOT_FOUND /*404*/) {
                                    // Use legacy request
                                    lookup3PidLegacy(address, medium, callback);
                                } else {
                                    super.onMatrixError(e);
                                }
                            }
                        },
                        null));
    }

    private void lookup3PidLegacy(String address, String medium, final ApiCallback<String> callback) {
        mApi.lookup3Pid(address, medium)
                .enqueue(new RestAdapterCallback<>("lookup3PidLegacy",
                        null,
                        new SimpleApiCallback<PidResponse>(callback) {
                            @Override
                            public void onSuccess(PidResponse info) {
                                callback.onSuccess((null == info.mxid) ? "" : info.mxid);
                            }
                        },
                        null));
    }

    /**
     * Request the ownership validation of an email address or a phone number previously set
     * by {@link ProfileRestClient#requestEmailValidationToken(String, String, int, String, boolean, ApiCallback)}
     *
     * @param medium       the medium of the 3pid
     * @param token        the token generated by the requestEmailValidationToken call
     * @param clientSecret the client secret which was supplied in the requestEmailValidationToken call
     * @param sid          the sid for the session
     * @param callback     asynchronous callback response
     */
    public void submitValidationToken(final String medium,
                                      final String token,
                                      final String clientSecret,
                                      final String sid,
                                      final ApiCallback<Boolean> callback) {
        mApi.requestOwnershipValidationV2(medium, token, clientSecret, sid)
                .enqueue(new RestAdapterCallback<>("submitValidationToken",
                        null,
                        new SimpleApiCallback<SuccessResult>(callback) {
                            @Override
                            public void onSuccess(SuccessResult info) {
                                callback.onSuccess(info.success);
                            }

                            @Override
                            public void onMatrixError(MatrixError e) {
                                if (e.mStatus == HttpURLConnection.HTTP_NOT_FOUND /*404*/) {
                                    // Use legacy request
                                    submitValidationTokenLegacy(medium, token, clientSecret, sid, callback);
                                } else {
                                    super.onMatrixError(e);
                                }
                            }
                        },
                        null));
    }

    private void submitValidationTokenLegacy(final String medium,
                                             final String token,
                                             final String clientSecret,
                                             final String sid,
                                             final ApiCallback<Boolean> callback) {
        mApi.requestOwnershipValidation(medium, token, clientSecret, sid)
                .enqueue(new RestAdapterCallback<>("submitValidationTokenLegacy",
                        null,
                        new SimpleApiCallback<SuccessResult>(callback) {
                            @Override
                            public void onSuccess(SuccessResult info) {
                                callback.onSuccess(info.success);
                            }
                        },
                        null));
    }

    /**
     * Retrieve user matrix id from a 3rd party id.
     *
     * @param addresses 3rd party ids
     * @param mediums   the media.
     * @param callback  the 3rd parties callback
     */
    public void lookup3Pids(final List<String> addresses, final List<String> mediums, final ApiCallback<List<String>> callback) {
        // sanity checks
        if ((null == addresses) || (null == mediums) || (addresses.size() != mediums.size())) {
            callback.onUnexpectedError(new Exception("invalid params"));
            return;
        }

        // nothing to check
        if (0 == mediums.size()) {
            callback.onSuccess(new ArrayList<>());
            return;
        }

        BulkLookupParams threePidsParams = new BulkLookupParams();

        List<List<String>> list = new ArrayList<>();

        for (int i = 0; i < addresses.size(); i++) {
            list.add(Arrays.asList(mediums.get(i), addresses.get(i)));
        }

        threePidsParams.threepids = list;

        mApi.bulkLookupV2(threePidsParams).enqueue(new RestAdapterCallback<>("lookup3Pids",
                null,
                new SimpleApiCallback<BulkLookupResponse>(callback) {
                    @Override
                    public void onSuccess(BulkLookupResponse info) {
                        handleBulkLookupSuccess(info, addresses, callback);
                    }

                    @Override
                    public void onMatrixError(MatrixError e) {
                        if (e.mStatus == HttpURLConnection.HTTP_NOT_FOUND /*404*/) {
                            // Use legacy request
                            lookup3PidsLegacy(addresses, threePidsParams, callback);
                        } else {
                            super.onMatrixError(e);
                        }
                    }
                },
                null));
    }

    private void lookup3PidsLegacy(final List<String> addresses, final BulkLookupParams threePidsParams, final ApiCallback<List<String>> callback) {
        mApi.bulkLookup(threePidsParams).enqueue(new RestAdapterCallback<>("lookup3PidsLegacy",
                null,
                new SimpleApiCallback<BulkLookupResponse>(callback) {
                    @Override
                    public void onSuccess(BulkLookupResponse info) {
                        handleBulkLookupSuccess(info, addresses, callback);
                    }
                },
                null));
    }

    private void handleBulkLookupSuccess(
            BulkLookupResponse bulkLookupResponse,
            List<String> addresses,
            ApiCallback<List<String>> callback) {
        Map<String, String> mxidByAddress = new HashMap<>();

        if (null != bulkLookupResponse.threepids) {
            for (int i = 0; i < bulkLookupResponse.threepids.size(); i++) {
                List<String> items = bulkLookupResponse.threepids.get(i);
                // [0] : medium
                // [1] : address
                // [2] : matrix id
                mxidByAddress.put(items.get(1), items.get(2));
            }
        }

        List<String> matrixIds = new ArrayList<>();

        for (String address : addresses) {
            if (mxidByAddress.containsKey(address)) {
                matrixIds.add(mxidByAddress.get(address));
            } else {
                matrixIds.add("");
            }
        }

        callback.onSuccess(matrixIds);
    }
}

@@ -1531,67 +1531,8 @@
 p;%0A%0A
-// FIXME Stop sending the matrix token for this request...%0A
 publ

Stop sending Matrix homeserver access token to the identity server.