/*
 * Copyright (C) 2017 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.server.timezone;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastXmlSerializer;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.io.PrintWriter;

import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE;
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS;
import static com.android.server.timezone.PackageStatus.CHECK_STARTED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;

/**
 * Storage logic for accessing/mutating the Android system's persistent state related to time zone
 * update checking. There is expected to be a single instance. All non-private methods are thread
 * safe.
 */
final class PackageStatusStorage {

    private static final String LOG_TAG = "timezone.PackageStatusStorage";

    private static final String TAG_PACKAGE_STATUS = "PackageStatus";

    /**
     * Attribute that stores a monotonically increasing lock ID, used to detect concurrent update
     * issues without on-line locks. Incremented on every write.
     */
    private static final String ATTRIBUTE_OPTIMISTIC_LOCK_ID = "optimisticLockId";

    /**
     * Attribute that stores the current "check status" of the time zone update application
     * packages.
     */
    private static final String ATTRIBUTE_CHECK_STATUS = "checkStatus";

    /**
     * Attribute that stores the version of the time zone rules update application being checked
     * / last checked.
     */
    private static final String ATTRIBUTE_UPDATE_APP_VERSION = "updateAppPackageVersion";

    /**
     * Attribute that stores the version of the time zone rules data application being checked
     * / last checked.
     */
    private static final String ATTRIBUTE_DATA_APP_VERSION = "dataAppPackageVersion";

    private static final long UNKNOWN_PACKAGE_VERSION = -1;

    private final AtomicFile mPackageStatusFile;

    PackageStatusStorage(File storageDir) {
        mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"), "timezone-status");
    }

    /**
     * Initialize any storage, as needed.
     *
     * @throws IOException if the storage could not be initialized
     */
    void initialize() throws IOException {
        if (!mPackageStatusFile.getBaseFile().exists()) {
            insertInitialPackageStatus();
        }
    }

    void deleteFileForTests() {
        synchronized(this) {
            mPackageStatusFile.delete();
        }
    }

    /**
     * Obtain the current check status of the application packages. Returns {@code null} the first
     * time it is called, or after {@link #resetCheckState()}.
     */
    PackageStatus getPackageStatus() {
        synchronized (this) {
            try {
                return getPackageStatusLocked();
            } catch (ParseException e) {
                // This means that data exists in the file but it was bad.
                Slog.e(LOG_TAG, "Package status invalid, resetting and retrying", e);

                // Reset the storage so it is in a good state again.
                recoverFromBadData(e);
                try {
                    return getPackageStatusLocked();
                } catch (ParseException e2) {
                    throw new IllegalStateException("Recovery from bad file failed", e2);
                }
            }
        }
    }

    @GuardedBy("this")
    private PackageStatus getPackageStatusLocked() throws ParseException {
        try (FileInputStream fis = mPackageStatusFile.openRead()) {
            XmlPullParser parser = parseToPackageStatusTag(fis);
            Integer checkStatus = getNullableIntAttribute(parser, ATTRIBUTE_CHECK_STATUS);
            if (checkStatus == null) {
                return null;
            }
            int updateAppVersion = getIntAttribute(parser, ATTRIBUTE_UPDATE_APP_VERSION);
            int dataAppVersion = getIntAttribute(parser, ATTRIBUTE_DATA_APP_VERSION);
            return new PackageStatus(checkStatus,
                    new PackageVersions(updateAppVersion, dataAppVersion));
        } catch (IOException e) {
            ParseException e2 = new ParseException("Error reading package status", 0);
            e2.initCause(e);
            throw e2;
        }
    }

    @GuardedBy("this")
    private int recoverFromBadData(Exception cause) {
        mPackageStatusFile.delete();
        try {
            return insertInitialPackageStatus();
        } catch (IOException e) {
            IllegalStateException fatal = new IllegalStateException(e);
            fatal.addSuppressed(cause);
            throw fatal;
        }
    }

    /** Insert the initial data, returning the optimistic lock ID */
    private int insertInitialPackageStatus() throws IOException {
        // Doesn't matter what it is, but we avoid the obvious starting value each time the data
        // is reset to ensure that old tokens are unlikely to work.
        final int initialOptimisticLockId = (int) System.currentTimeMillis();

        writePackageStatusLocked(null /* status */, initialOptimisticLockId,
                null /* packageVersions */);
        return initialOptimisticLockId;
    }

    /**
     * Generate a new {@link CheckToken} that can be passed to the time zone rules update
     * application.
     */
    CheckToken generateCheckToken(PackageVersions currentInstalledVersions) {
        if (currentInstalledVersions == null) {
            throw new NullPointerException("currentInstalledVersions == null");
        }

        synchronized (this) {
            int optimisticLockId;
            try {
                optimisticLockId = getCurrentOptimisticLockId();
            } catch (ParseException e) {
                Slog.w(LOG_TAG, "Unable to find optimistic lock ID from package status");

                // Recover.
                optimisticLockId = recoverFromBadData(e);
            }

            int newOptimisticLockId = optimisticLockId + 1;
            try {
                boolean statusUpdated = writePackageStatusWithOptimisticLockCheck(
                        optimisticLockId, newOptimisticLockId, CHECK_STARTED,
                        currentInstalledVersions);
                if (!statusUpdated) {
                    throw new IllegalStateException("Unable to update status to CHECK_STARTED."
                            + " synchronization failure?");
                }
                return new CheckToken(newOptimisticLockId, currentInstalledVersions);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    /**
     * Reset the current device state to "unknown".
     */
    void resetCheckState() {
        synchronized(this) {
            int optimisticLockId;
            try {
                optimisticLockId = getCurrentOptimisticLockId();
            } catch (ParseException e) {
                Slog.w(LOG_TAG, "resetCheckState: Unable to find optimistic lock ID from package"
                        + " status");
                // Attempt to recover the storage state.
                optimisticLockId = recoverFromBadData(e);
            }

            int newOptimisticLockId = optimisticLockId + 1;
            try {
                if (!writePackageStatusWithOptimisticLockCheck(optimisticLockId,
                        newOptimisticLockId, null /* status */, null /* packageVersions */)) {
                    throw new IllegalStateException("resetCheckState: Unable to reset package"
                            + " status, newOptimisticLockId=" + newOptimisticLockId);
                }
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    /**
     * Update the current device state if possible. Returns true if the update was successful.
     * {@code false} indicates the storage has been changed since the {@link CheckToken} was
     * generated and the update was discarded.
     */
    boolean markChecked(CheckToken checkToken, boolean succeeded) {
        synchronized (this) {
            int optimisticLockId = checkToken.mOptimisticLockId;
            int newOptimisticLockId = optimisticLockId + 1;
            int status = succeeded ? CHECK_COMPLETED_SUCCESS : CHECK_COMPLETED_FAILURE;
            try {
                return writePackageStatusWithOptimisticLockCheck(optimisticLockId,
                        newOptimisticLockId, status, checkToken.mPackageVersions);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    @GuardedBy("this")
    private int getCurrentOptimisticLockId() throws ParseException {
        try (FileInputStream fis = mPackageStatusFile.openRead()) {
            XmlPullParser parser = parseToPackageStatusTag(fis);
            return getIntAttribute(parser, ATTRIBUTE_OPTIMISTIC_LOCK_ID);
        } catch (IOException e) {
            ParseException e2 = new ParseException("Unable to read file", 0);
            e2.initCause(e);
            throw e2;
        }
    }

    /** Returns a parser or throws ParseException, never returns null. */
    private static XmlPullParser parseToPackageStatusTag(FileInputStream fis)
            throws ParseException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(fis, StandardCharsets.UTF_8.name());
            int type;
            while ((type = parser.next()) != END_DOCUMENT) {
                final String tag = parser.getName();
                if (type == START_TAG && TAG_PACKAGE_STATUS.equals(tag)) {
                    return parser;
                }
            }
            throw new ParseException("Unable to find " + TAG_PACKAGE_STATUS + " tag", 0);
        } catch (XmlPullParserException e) {
            throw new IllegalStateException("Unable to configure parser", e);
        } catch (IOException e) {
            ParseException e2 = new ParseException("Error reading XML", 0);
            e.initCause(e);
            throw e2;
        }
    }

    @GuardedBy("this")
    private boolean writePackageStatusWithOptimisticLockCheck(int optimisticLockId,
            int newOptimisticLockId, Integer status, PackageVersions packageVersions)
            throws IOException {

        int currentOptimisticLockId;
        try {
            currentOptimisticLockId = getCurrentOptimisticLockId();
            if (currentOptimisticLockId != optimisticLockId) {
                return false;
            }
        } catch (ParseException e) {
            recoverFromBadData(e);
            return false;
        }

        writePackageStatusLocked(status, newOptimisticLockId, packageVersions);
        return true;
    }

    @GuardedBy("this")
    private void writePackageStatusLocked(Integer status, int optimisticLockId,
            PackageVersions packageVersions) throws IOException {
        if ((status == null) != (packageVersions == null)) {
            throw new IllegalArgumentException(
                    "Provide both status and packageVersions, or neither.");
        }

        FileOutputStream fos = null;
        try {
            fos = mPackageStatusFile.startWrite();
            XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(fos, StandardCharsets.UTF_8.name());
            serializer.startDocument(null /* encoding */, true /* standalone */);
            final String namespace = null;
            serializer.startTag(namespace, TAG_PACKAGE_STATUS);
            String statusAttributeValue = status == null ? "" : Integer.toString(status);
            serializer.attribute(namespace, ATTRIBUTE_CHECK_STATUS, statusAttributeValue);
            serializer.attribute(namespace, ATTRIBUTE_OPTIMISTIC_LOCK_ID,
                    Integer.toString(optimisticLockId));
            long updateAppVersion = status == null
                    ? UNKNOWN_PACKAGE_VERSION : packageVersions.mUpdateAppVersion;
            serializer.attribute(namespace, ATTRIBUTE_UPDATE_APP_VERSION,
                    Long.toString(updateAppVersion));
            long dataAppVersion = status == null
                    ? UNKNOWN_PACKAGE_VERSION : packageVersions.mDataAppVersion;
            serializer.attribute(namespace, ATTRIBUTE_DATA_APP_VERSION,
                    Long.toString(dataAppVersion));
            serializer.endTag(namespace, TAG_PACKAGE_STATUS);
            serializer.endDocument();
            serializer.flush();
            mPackageStatusFile.finishWrite(fos);
        } catch (IOException e) {
            if (fos != null) {
                mPackageStatusFile.failWrite(fos);
            }
            throw e;
        }

    }

    /** Only used during tests to force a known table state. */
    public void forceCheckStateForTests(int checkStatus, PackageVersions packageVersions)
            throws IOException {
        synchronized (this) {
            try {
                final int initialOptimisticLockId = (int) System.currentTimeMillis();
                writePackageStatusLocked(checkStatus, initialOptimisticLockId, packageVersions);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    private static Integer getNullableIntAttribute(XmlPullParser parser, String attributeName)
            throws ParseException {
        String attributeValue = parser.getAttributeValue(null, attributeName);
        try {
            if (attributeValue == null) {
                throw new ParseException("Attribute " + attributeName + " missing", 0);
            } else if (attributeValue.isEmpty()) {
                return null;
            }
            return Integer.parseInt(attributeValue);
        } catch (NumberFormatException e) {
            throw new ParseException(
                    "Bad integer for attributeName=" + attributeName + ": " + attributeValue, 0);
        }
    }

    private static int getIntAttribute(XmlPullParser parser, String attributeName)
            throws ParseException {
        Integer value = getNullableIntAttribute(parser, attributeName);
        if (value == null) {
            throw new ParseException("Missing attribute " + attributeName, 0);
        }
        return value;
    }

    public void dump(PrintWriter printWriter) {
        printWriter.println("Package status: " + getPackageStatus());
    }
}
