#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#if USE_SYSLOG
#include <syslog.h>
#endif
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "extern.h"
#include "watch_err.h"

#include <cutils/properties.h>
#include <flash_ts.h>

#define min(a,b) (((a) < (b)) ? (a) : (b))

// Table of boolean system properties which will be synced with fts.
static const char *kKeyProperty[] = {
    // property recording first activation date.
    "persist.chrome.activation_date",
#if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    // property recording device UMA client id, not linked with serial number.
    "persist.chrome.client_id",
#endif  // #if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    // property recording total number of FDR events to date.
    "persist.chrome.fdr_count",
    // property recording total number of FDR events to date, but incremented
    // in fts.
    "persist.fdr_watchdog",
#if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    // property recording user opt-out of sending usage report. Keep the name
    // as "opt_in" for backward-compatibility, see "usage_report" below.
    "persist.chrome.opt_in.stats",
#endif  // #if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    // property recording whether omaha checkin has occurred.
    "persist.omaha.checkin",
    // property for device color set in factory.
    "persist.color",
    // property for country code set in factory.
    "ro.country",
    // property for language tag set in factory.
    "ro.lang",
    // property set to 'true' if supports low vcore. 'false' otherwise.
    "ro.low_vcore_enabled",
};

// Matching fts keys for above properties.
static const char *kKeyFTS[] = {
    "activation_date",
#if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    "client_id",
#endif  // #if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    "fdr_count",
    "fdr_watchdog",
#if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    // usage_report should be interpreted as opt-out, i.e.
    // usage_report=0 means user opt out of sending usage_report;
    // usage_report=1 means user did not opt out.
    "usage_report",
#endif  // #if !defined(REMOVE_UMA_CONTENT_FROM_FTS)
    "omaha_checkin",
    "color",
    "ro.country",
    "ro.lang",
    "ro.low_vcore_enabled",
};

static int open_fts() {
    int fd = open(FTS_DEVICE, O_RDWR);
    if (fd == -1) {
        // Only print out the warning once to avoid flooding log.
        static int warned = 0;
        if (warned) return -1;
        warned = 1;

#if USE_SYSLOG
        syslog(LOG_ERR,
#else
        fprintf(stderr,
#endif
               "error open %s: %s\n", FTS_DEVICE, strerror(errno));
    }
    return fd;
}

// Helper to read FTS property.
static int read_fts_property(const int fd, struct flash_ts_io_req *req,
                             const char *key) {
    if (!req || !key || fd < 0) return -1;
    memset(req, 0, sizeof(*req));
    snprintf(req->key, sizeof(req->key), "%s", key);
    if (ioctl(fd, FLASH_TS_IO_GET, req)) {
#if USE_SYSLOG
        syslog(LOG_ERR,
#else
        fprintf(stderr,
#endif
               "ioctl FLASH_TS_IO_GET fail %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

static int write_fts_property(const int fd, const char *key, const char *value) {
    if (!key || !value || fd < 0) return -1;

    struct flash_ts_io_req req;
    memset(&req, 0, sizeof(req));
    snprintf(req.key, sizeof(req.key), "%s", key);
    snprintf(req.val, sizeof(req.val), "%s", value);
    if (ioctl(fd, FLASH_TS_IO_SET, &req)) {
#if USE_SYSLOG
        syslog(LOG_ERR,
#else
        fprintf(stderr,
#endif
               "ioctl FLASH_TS_IO_SET fail %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

// Sync information between system properties and fts.
//
// The fts_to_prop parameter indicates the direction.
//
// We sync from fts to properties only at boot.
//
// We sync from properties to fts periodically so that
// the properties become persistent across FDRs.
//
// Some properties (e.g. ro.*) are only sync'ed one-way.
static void sync_properties_fts(int fts_to_prop) {
    // open fts
    int fd = open_fts();
    if (fd < 0) return;

    for (size_t index = 0; index < sizeof(kKeyProperty) / sizeof(*kKeyProperty);
         ++index) {
        int ro_prop = (strncmp("ro.", kKeyProperty[index], 3) == 0);
        // Only copy read-only fts values to properties, not the other way.
        // This means that these properties can only be set by changing the
        // FTS.
        //
        // Note: we could change this behavior if we wanted this
        // functionality.
        if ((ro_prop || !strcmp(kKeyFTS[index], "fdr_watchdog")) &&
            !fts_to_prop) {
            continue;
        }

        // read fts
        struct flash_ts_io_req req;
        if (read_fts_property(fd, &req, kKeyFTS[index]) == -1) {
            close(fd);
            return;
        }

        // read property
        char value[PROPERTY_VALUE_MAX];
        property_get(kKeyProperty[index], value, "");

        // If values are identical, there is nothing to do.
        if (strncmp(value, req.val, min(sizeof(req.val), PROPERTY_VALUE_MAX)) ==
            0) {
            continue;
        }

        // Sync them based on direction and values.
        // We always want to overwrite the FDR property.
        if (fts_to_prop &&
            (*value == '\0' || !strcmp(kKeyFTS[index], "fdr_watchdog"))) {
            // We are running the one-time initialization script.
            //
            // If a property is unset (and therefore the fts must be set)
            // then initialize the property to the fts value.
            //
            // If a property is set (and our fts hasn't been set yet),
            // then do nothing.  The next sync after booting will remedy
            // this
            // discrepancy.  This could happen if we reboot after
            // the property is set, but before the fts is synced.
            property_set(kKeyProperty[index], req.val);
        } else if (!fts_to_prop && *value != '\0') {
            // We are running the periodic sync process.
            //
            // If a property is set (and the fts value is different
            // or unset), set fts to the current property value.
            //
            // Note: we don't support clearing the fts
            // (accidentally or intentionally) as these properties
            // are intended to be sticky.  For example, removing
            // /data/properties/* or doing a setprop with a null
            // value won't change fts.  This doesn't normally occur
            // and the value will be reset at next boot.
            if (write_fts_property(fd, kKeyFTS[index], value) == -1) {
                close(fd);
                return;
            }
        }
    }

    close(fd);
}

// helper functions which sync in each direction.
void copy_fts_to_properties() {
  sync_properties_fts(1);
}

void copy_properties_to_fts() {
  sync_properties_fts(0);
}

void increment_fdr_count() {
    // Only increment once maximum per session, to avoid edge cases such as the
    // app + button causing fdr at the same time and the count incrementing
    // twice.
    static int fdr_incremented = 0;
    if (fdr_incremented) return;
    ++fdr_incremented;

    int fd = open_fts();
    if (fd < 0) {
        return;
    }

    struct flash_ts_io_req req;
    if (read_fts_property(fd, &req, "fdr_watchdog") == -1) {
        close(fd);
        return;
    }

    int fdr_count = strtol(req.val, NULL, 10);

    char fdr_count_str[FLASH_TS_MAX_VAL_SIZE];
    sprintf(fdr_count_str, "%d", fdr_count + 1);
    write_fts_property(fd, req.key, fdr_count_str);
    close(fd);
}
