/*
 * Copyright (C) 2015 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.tools.build.apkzlib.zip;

import com.android.tools.build.apkzlib.zip.utils.LittleEndianUtils;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * The ZipField class represents a field in a record in a zip file. Zip files are made with records
 * that have fields. This class makes it easy to read, write and verify field values.
 * <p>
 * There are two main types of fields: 2-byte fields and 4-byte fields. We represent each one as
 * a subclass of {@code ZipField}, {@code F2} for the 2-byte field and {@code F4} for the 4-byte
 * field. Because Java's {@code int} data type is guaranteed to be 4-byte, all methods use Java's
 * native {@link int} as data type.
 * <p>
 * For each field we can either read, write or verify. Verification is used for fields whose value
 * we know. Some fields, <em>e.g.</em> signature fields, have fixed value. Other fields have
 * variable values, but in some situations we know which value they have. For example, the last
 * modification time of a file's local header will have to match the value of the file's
 * modification time as stored in the central directory.
 * <p>
 * Because records are compact, <em>i.e.</em> fields are stored sequentially with no empty spaces,
 * fields are generally created in the sequence they exist and the end offset of a field is used
 * as the offset of the next one. The end of a field can be obtained by invoking
 * {@link #endOffset()}. This allows creating fields in sequence without doing offset computation:
 * <pre>
 * ZipField.F2 firstField = new ZipField.F2(0, "First field");
 * ZipField.F4 secondField = new ZipField(firstField.endOffset(), "Second field");
 * </pre>
 */
abstract class ZipField {

    /**
     * Field name. Used for providing (more) useful error messages.
     */
    @Nonnull
    private final String name;

    /**
     * Offset of the file in the record.
     */
    protected final int offset;

    /**
     * Size of the field. Only 2 or 4 allowed.
     */
    private final int size;

    /**
     * If a fixed value exists for the field, then this attribute will contain that value.
     */
    @Nullable
    private final Long expected;

    /**
     * All invariants that this field must verify.
     */
    @Nonnull
    private Set<ZipFieldInvariant> invariants;

    /**
     * Creates a new field that does not contain a fixed value.
     *
     * @param offset the field's offset in the record
     * @param size the field size
     * @param name the field's name
     * @param invariants the invariants that must be verified by the field
     */
    ZipField(int offset, int size, @Nonnull String name, ZipFieldInvariant... invariants) {
        Preconditions.checkArgument(offset >= 0, "offset >= 0");
        Preconditions.checkArgument(size == 2 || size == 4, "size != 2 && size != 4");

        this.name = name;
        this.offset = offset;
        this.size = size;
        expected = null;
        this.invariants = Sets.newHashSet(invariants);
    }

    /**
     * Creates a new field that contains a fixed value.
     *
     * @param offset the field's offset in the record
     * @param size the field size
     * @param expected the expected field value
     * @param name the field's name
     */
    ZipField(int offset, int size, long expected, @Nonnull String name) {
        Preconditions.checkArgument(offset >= 0, "offset >= 0");
        Preconditions.checkArgument(size == 2 || size == 4, "size != 2 && size != 4");

        this.name = name;
        this.offset = offset;
        this.size = size;
        this.expected = expected;
        invariants = Sets.newHashSet();
    }

    /**
     * Checks whether a value verifies the field's invariants. Nothing happens if the value verifies
     * the invariants.
     *
     * @param value the value
     * @throws IOException the invariants are not verified
     */
    private void checkVerifiesInvariants(long value) throws IOException {
        for (ZipFieldInvariant invariant : invariants) {
            if (!invariant.isValid(value)) {
                throw new IOException("Value " + value + " of field " + name + " is invalid "
                        + "(fails '" + invariant.getName() + "').");
            }
        }
    }

    /**
     * Advances the position in the provided byte buffer by the size of this field.
     *
     * @param bytes the byte buffer; at the end of the method its position will be greater by
     * the size of this field
     * @throws IOException failed to advance the buffer
     */
    void skip(@Nonnull ByteBuffer bytes) throws IOException {
        if (bytes.remaining() < size) {
            throw new IOException("Cannot skip field " + name + " because only "
                    + bytes.remaining() + " remain in the buffer.");
        }

        bytes.position(bytes.position() + size);
    }

    /**
     * Reads a field value.
     *
     * @param bytes the byte buffer with the record data; after this method finishes, the buffer
     * will be positioned at the first byte after the field
     * @return the value of the field
     * @throws IOException failed to read the field
     */
    long read(@Nonnull ByteBuffer bytes) throws IOException {
        if (bytes.remaining() < size) {
            throw new IOException("Cannot skip field " + name + " because only "
                    + bytes.remaining() + " remain in the buffer.");
        }

        bytes.order(ByteOrder.LITTLE_ENDIAN);

        long r;
        if (size == 2) {
            r = LittleEndianUtils.readUnsigned2Le(bytes);
        } else {
            r =  LittleEndianUtils.readUnsigned4Le(bytes);
        }

        checkVerifiesInvariants(r);
        return r;
    }

    /**
     * Verifies that the field at the current buffer position has the expected value. The field
     * must have been created with the constructor that defines the expected value.
     *
     * @param bytes the byte buffer with the record data; after this method finishes, the buffer
     * will be positioned at the first byte after the field
     * @throws IOException failed to read the field or the field does not have the expected value
     */
    void verify(@Nonnull ByteBuffer bytes) throws IOException {
        verify(bytes, null);
    }

    /**
     * Verifies that the field at the current buffer position has the expected value. The field
     * must have been created with the constructor that defines the expected value.
     *
     * @param bytes the byte buffer with the record data; after this method finishes, the buffer
     * will be positioned at the first byte after the field
     * @param verifyLog if non-{@code null}, will log the verification error
     * @throws IOException failed to read the data or the field does not have the expected value;
     * only thrown if {@code verifyLog} is {@code null}
     */
    void verify(@Nonnull ByteBuffer bytes, @Nullable VerifyLog verifyLog) throws IOException {
        Preconditions.checkState(expected != null, "expected == null");
        verify(bytes, expected, verifyLog);
    }

    /**
     * Verifies that the field has an expected value.
     *
     * @param bytes the byte buffer with the record data; after this method finishes, the buffer
     * will be positioned at the first byte after the field
     * @param expected the value we expect the field to have; if this field has invariants, the
     * value must verify them
     * @throws IOException failed to read the data or the field does not have the expected value
     */
    void verify(@Nonnull ByteBuffer bytes, long expected) throws IOException {
        verify(bytes, expected, null);
    }

    /**
     * Verifies that the field has an expected value.
     *
     * @param bytes the byte buffer with the record data; after this method finishes, the buffer
     * will be positioned at the first byte after the field
     * @param expected the value we expect the field to have; if this field has invariants, the
     * value must verify them
     * @param verifyLog if non-{@code null}, will log the verification error
     * @throws IOException failed to read the data or the field does not have the expected value;
     * only thrown if {@code verifyLog} is {@code null}
     */
    void verify(
            @Nonnull ByteBuffer bytes,
            long expected,
            @Nullable VerifyLog verifyLog) throws IOException {
        checkVerifiesInvariants(expected);
        long r = read(bytes);
        if (r != expected) {
            String error =
                    String.format(
                            "Incorrect value for field '%s': value is %s but %s expected.",
                            name,
                            r,
                            expected);

            if (verifyLog == null) {
                throw new IOException(error);
            } else {
                verifyLog.log(error);
            }
        }
    }

    /**
     * Writes the value of the field.
     *
     * @param output where to write the field; the field will be written at the current position
     * of the buffer
     * @param value the value to write
     * @throws IOException failed to write the value in the stream
     */
    void write(@Nonnull ByteBuffer output, long value) throws IOException {
        checkVerifiesInvariants(value);

        Preconditions.checkArgument(value >= 0, "value (%s) < 0", value);

        if (size == 2) {
            Preconditions.checkArgument(value <= 0x0000ffff, "value (%s) > 0x0000ffff", value);
            LittleEndianUtils.writeUnsigned2Le(output, Ints.checkedCast(value));
        } else {
            Verify.verify(size == 4);
            Preconditions.checkArgument(value <= 0x00000000ffffffffL,
                    "value (%s) > 0x00000000ffffffffL", value);
            LittleEndianUtils.writeUnsigned4Le(output, value);
        }
    }

    /**
     * Writes the value of the field. The field must have an expected value set in the constructor.
     *
     * @param output where to write the field; the field will be written at the current position
     * of the buffer
     * @throws IOException failed to write the value in the stream
     */
    void write(@Nonnull ByteBuffer output) throws IOException {
        Preconditions.checkState(expected != null, "expected == null");
        write(output, expected);
    }

    /**
     * Obtains the offset at which the field starts.
     *
     * @return the start offset
     */
    int offset() {
        return offset;
    }

    /**
     * Obtains the offset at which the field ends. This is the exact offset at which the next
     * field starts.
     *
     * @return the end offset
     */
    int endOffset() {
        return offset + size;
    }

    /**
     * Concrete implementation of {@link ZipField} that represents a 2-byte field.
     */
    static class F2 extends ZipField {

        /**
         * Creates a new field.
         *
         * @param offset the field's offset in the record
         * @param name the field's name
         * @param invariants the invariants that must be verified by the field
         */
        F2(int offset, @Nonnull String name, ZipFieldInvariant... invariants) {
            super(offset, 2, name, invariants);
        }

        /**
         * Creates a new field that contains a fixed value.
         *
         * @param offset the field's offset in the record
         * @param expected the expected field value
         * @param name the field's name
         */
        F2(int offset, long expected, @Nonnull String name) {
            super(offset, 2, expected, name);
        }
    }

    /**
     * Concrete implementation of {@link ZipField} that represents a 4-byte field.
     */
    static class F4 extends ZipField {
        /**
         * Creates a new field.
         *
         * @param offset the field's offset in the record
         * @param name the field's name
         * @param invariants the invariants that must be verified by the field
         */
        F4(int offset, @Nonnull String name, ZipFieldInvariant... invariants) {
            super(offset, 4, name, invariants);
        }

        /**
         * Creates a new field that contains a fixed value.
         *
         * @param offset the field's offset in the record
         * @param expected the expected field value
         * @param name the field's name
         */
        F4(int offset, long expected, @Nonnull String name) {
            super(offset, 4, expected, name);
        }
    }
}
