/*
 * Copyright (C) 2018 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.example.android.systemupdatersample.util;

import android.annotation.TargetApi;
import android.os.Build;

import com.example.android.systemupdatersample.PayloadSpec;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/** The helper class that creates {@link PayloadSpec}. */
@TargetApi(Build.VERSION_CODES.N)
public final class PayloadSpecs {

    /**
     * The payload PAYLOAD_ENTRY is stored in the zip package to comply with the Android OTA package
     * format. We want to find out the offset of the entry, so that we can pass it over to the A/B
     * updater without making an extra copy of the payload.
     *
     * <p>According to Android docs, the entries are listed in the order in which they appear in the
     * zip file. So we enumerate the entries to identify the offset of the payload file.
     * http://developer.android.com/reference/java/util/zip/ZipFile.html#entries()
     */
    public static PayloadSpec forNonStreaming(File packageFile) throws IOException {
        boolean payloadFound = false;
        long payloadOffset = 0;
        long payloadSize = 0;

        List<String> properties = new ArrayList<>();
        try (ZipFile zip = new ZipFile(packageFile)) {
            Enumeration<? extends ZipEntry> entries = zip.entries();
            long offset = 0;
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                String name = entry.getName();
                // Zip local file header has 30 bytes + filename + sizeof extra field.
                // https://en.wikipedia.org/wiki/Zip_(file_format)
                long extraSize = entry.getExtra() == null ? 0 : entry.getExtra().length;
                offset += 30 + name.length() + extraSize;

                if (entry.isDirectory()) {
                    continue;
                }

                long length = entry.getCompressedSize();
                if (PackagePropertyFiles.PAYLOAD_BINARY_FILE_NAME.equals(name)) {
                    if (entry.getMethod() != ZipEntry.STORED) {
                        throw new IOException("Invalid compression method.");
                    }
                    payloadFound = true;
                    payloadOffset = offset;
                    payloadSize = length;
                } else if (PackagePropertyFiles.PAYLOAD_PROPERTIES_FILE_NAME.equals(name)) {
                    InputStream inputStream = zip.getInputStream(entry);
                    if (inputStream != null) {
                        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                        String line;
                        while ((line = br.readLine()) != null) {
                            properties.add(line);
                        }
                    }
                }
                offset += length;
            }
        }

        if (!payloadFound) {
            throw new IOException("Failed to find payload entry in the given package.");
        }
        return PayloadSpec.newBuilder()
                        .url("file://" + packageFile.getAbsolutePath())
                        .offset(payloadOffset)
                        .size(payloadSize)
                        .properties(properties)
                        .build();
    }

    /**
     * Converts an {@link PayloadSpec} to a string.
     */
    public static String toString(PayloadSpec payloadSpec) {
        return "<PayloadSpec url=" + payloadSpec.getUrl()
                + ", offset=" + payloadSpec.getOffset()
                + ", size=" + payloadSpec.getSize()
                + ", properties=" + Arrays.toString(
                        payloadSpec.getProperties().toArray(new String[0]))
                + ">";
    }

    private PayloadSpecs() {}

}
