/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * resarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#include <string.h>
#include <errno.h>
#include <assert.h>

#include "os/mynewt.h"

#include "sensor/sensor.h"
#include "sensor/mag.h"

#include "sim/sim_mag.h"

/* Exports for the sensor interface.
 */
static int sim_mag_sensor_read(struct sensor *, sensor_type_t,
        sensor_data_func_t, void *, uint32_t);
static int sim_mag_sensor_get_config(struct sensor *, sensor_type_t,
        struct sensor_cfg *);

static const struct sensor_driver g_sim_mag_sensor_driver = {
    sim_mag_sensor_read,
    sim_mag_sensor_get_config
};

/**
 * Expects to be called back through os_dev_create().
 *
 * @param The device object associated with this magnetometer
 * @param Argument passed to OS device init, unused
 *
 * @return 0 on success, non-zero error on failure.
 */
int
sim_mag_init(struct os_dev *dev, void *arg)
{
    struct sim_mag *sm;
    struct sensor *sensor;
    int rc;

    sm = (struct sim_mag *) dev;

    sensor = &sm->sm_sensor;

    rc = sensor_init(sensor, dev);
    if (rc != 0) {
        goto err;
    }

    rc = sensor_set_driver(sensor, SENSOR_TYPE_MAGNETIC_FIELD,
            (struct sensor_driver *) &g_sim_mag_sensor_driver);
    if (rc != 0) {
        goto err;
    }

    rc = sensor_mgr_register(sensor);
    if (rc != 0) {
        goto err;
    }

    return (0);
err:
    return (rc);
}

int
sim_mag_config(struct sim_mag *sm, struct sim_mag_cfg *cfg)
{
    /* Overwrite the configuration associated with this generic magnetometer. */
    memcpy(&sm->sm_cfg, cfg, sizeof(*cfg));

    return (0);
}

static int
sim_mag_sensor_read(struct sensor *sensor, sensor_type_t type,
        sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
{
    struct sim_mag *sm;
    struct sensor_mag_data smd;
    os_time_t now;
    uint32_t num_samples;
    int i;
    int rc;

    /* If the read isn't looking for mag data, then don't do anything. */
    if (!(type & SENSOR_TYPE_MAGNETIC_FIELD)) {
        rc = SYS_EINVAL;
        goto err;
    }

    sm = (struct sim_mag *) SENSOR_GET_DEVICE(sensor);

    /* When a sensor is "read", we get the last 'n' samples from the device
     * and pass them to the sensor data function.  Based on the sample
     * interval provided to sim_mag_config() and the last time this function
     * was called, 'n' samples are generated.
     */
    now = os_time_get();

    num_samples = (now - sm->sm_last_read_time) / sm->sm_cfg.smc_sample_itvl;
    num_samples = min(num_samples, sm->sm_cfg.smc_nr_samples);

    /* By default only readings are provided for 1-axis (x), however,
     * if number of axises is configured, up to 3-axises of data can be
     * returned.
     */
    smd.smd_x = 0.0;
    smd.smd_y = 0.0;
    smd.smd_z = 0.0;

    smd.smd_x_is_valid = 1;
    smd.smd_y_is_valid = 0;
    smd.smd_z_is_valid = 0;

    if (sm->sm_cfg.smc_nr_axises > 1) {
        smd.smd_y = 0.0;
    }
    if (sm->sm_cfg.smc_nr_axises > 2) {
        smd.smd_z = 0.0;
    }

    /* Call data function for each of the generated readings. */
    for (i = 0; i < num_samples; i++) {
        rc = data_func(sensor, data_arg, &smd, SENSOR_TYPE_MAGNETIC_FIELD);
        if (rc != 0) {
            goto err;
        }
    }

    return (0);
err:
    return (rc);
}

static int
sim_mag_sensor_get_config(struct sensor *sensor, sensor_type_t type,
        struct sensor_cfg *cfg)
{
    int rc;

    if (type != SENSOR_TYPE_MAGNETIC_FIELD) {
        rc = SYS_EINVAL;
        goto err;
    }

    cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT_TRIPLET;

    return (0);
err:
    return (rc);
}
