/*
 * 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 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,
            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,
            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, 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, Map<String, String> headers) {
        this(
                HttpURLConnection.HTTP_OK,
                data,
                headers,
                /* notModified= */ false,
                /* networkTimeMs= */ 0);
    }

    private NetworkResponse(
            int statusCode,
            byte[] data,
            Map<String, String> headers,
            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.
     */
    public final Map<String, String> headers;

    /** All response headers. Must not be mutated directly. */
    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;

    private static Map<String, String> toHeaderMap(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;
    }

    private static List<Header> toAllHeaderList(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;
    }
}
