/*
 * 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"));
    }

    /**
     * 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());
    }
}
