/*
 * Copyright (C) 2011 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.android.volley;

import androidx.annotation.Nullable;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/** Data and headers returned from {@link Network#performRequest(Request)}. */
public class NetworkResponse {

    /**
     * Creates a new network response.
     *
     * @param statusCode the HTTP status code
     * @param data Response body
     * @param headers Headers returned with this response, or null for none
     * @param notModified True if the server returned a 304 and the data was already in cache
     * @param networkTimeMs Round-trip network time to receive network response
     * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
     *     cannot handle server responses containing multiple headers with the same name. This
     *     constructor may be removed in a future release of Volley.
     */
    @Deprecated
    public NetworkResponse(
            int statusCode,
            byte[] data,
            @Nullable Map<String, String> headers,
            boolean notModified,
            long networkTimeMs) {
        this(statusCode, data, headers, toAllHeaderList(headers), notModified, networkTimeMs);
    }

    /**
     * Creates a new network response.
     *
     * @param statusCode the HTTP status code
     * @param data Response body
     * @param notModified True if the server returned a 304 and the data was already in cache
     * @param networkTimeMs Round-trip network time to receive network response
     * @param allHeaders All headers returned with this response, or null for none
     */
    public NetworkResponse(
            int statusCode,
            byte[] data,
            boolean notModified,
            long networkTimeMs,
            @Nullable List<Header> allHeaders) {
        this(statusCode, data, toHeaderMap(allHeaders), allHeaders, notModified, networkTimeMs);
    }

    /**
     * Creates a new network response.
     *
     * @param statusCode the HTTP status code
     * @param data Response body
     * @param headers Headers returned with this response, or null for none
     * @param notModified True if the server returned a 304 and the data was already in cache
     * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
     *     cannot handle server responses containing multiple headers with the same name. This
     *     constructor may be removed in a future release of Volley.
     */
    @Deprecated
    public NetworkResponse(
            int statusCode,
            byte[] data,
            @Nullable Map<String, String> headers,
            boolean notModified) {
        this(statusCode, data, headers, notModified, /* networkTimeMs= */ 0);
    }

    /**
     * Creates a new network response for an OK response with no headers.
     *
     * @param data Response body
     */
    public NetworkResponse(byte[] data) {
        this(
                HttpURLConnection.HTTP_OK,
                data,
                /* notModified= */ false,
                /* networkTimeMs= */ 0,
                Collections.<Header>emptyList());
    }

    /**
     * Creates a new network response for an OK response.
     *
     * @param data Response body
     * @param headers Headers returned with this response, or null for none
     * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
     *     cannot handle server responses containing multiple headers with the same name. This
     *     constructor may be removed in a future release of Volley.
     */
    @Deprecated
    public NetworkResponse(byte[] data, @Nullable Map<String, String> headers) {
        this(
                HttpURLConnection.HTTP_OK,
                data,
                headers,
                /* notModified= */ false,
                /* networkTimeMs= */ 0);
    }

    private NetworkResponse(
            int statusCode,
            byte[] data,
            @Nullable Map<String, String> headers,
            @Nullable List<Header> allHeaders,
            boolean notModified,
            long networkTimeMs) {
        this.statusCode = statusCode;
        this.data = data;
        this.headers = headers;
        if (allHeaders == null) {
            this.allHeaders = null;
        } else {
            this.allHeaders = Collections.unmodifiableList(allHeaders);
        }
        this.notModified = notModified;
        this.networkTimeMs = networkTimeMs;
    }

    /** The HTTP status code. */
    public final int statusCode;

    /** Raw data from this response. */
    public final byte[] data;

    /**
     * Response headers.
     *
     * <p>This map is case-insensitive. It should not be mutated directly.
     *
     * <p>Note that if the server returns two headers with the same (case-insensitive) name, this
     * map will only contain the last one. Use {@link #allHeaders} to inspect all headers returned
     * by the server.
     */
    @Nullable public final Map<String, String> headers;

    /** All response headers. Must not be mutated directly. */
    @Nullable public final List<Header> allHeaders;

    /** True if the server returned a 304 (Not Modified). */
    public final boolean notModified;

    /** Network roundtrip time in milliseconds. */
    public final long networkTimeMs;

    @Nullable
    private static Map<String, String> toHeaderMap(@Nullable List<Header> allHeaders) {
        if (allHeaders == null) {
            return null;
        }
        if (allHeaders.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        // Later elements in the list take precedence.
        for (Header header : allHeaders) {
            headers.put(header.getName(), header.getValue());
        }
        return headers;
    }

    @Nullable
    private static List<Header> toAllHeaderList(@Nullable Map<String, String> headers) {
        if (headers == null) {
            return null;
        }
        if (headers.isEmpty()) {
            return Collections.emptyList();
        }
        List<Header> allHeaders = new ArrayList<>(headers.size());
        for (Map.Entry<String, String> header : headers.entrySet()) {
            allHeaders.add(new Header(header.getKey(), header.getValue()));
        }
        return allHeaders;
    }
}
