from flask import Flask, jsonify, abort, make_response, request

NOT_FOUND = 'Not found'
BAD_REQUEST = 'Bad request'

app = Flask(__name__)

sensors = [
    {
        "id": 1,
        "description": "espclient1",
        "sensor_name": "temperature_dht11",
        "value": 25,
    },
    {
        "id": 2,
        "description": "espclient1",
        "sensor_name": "humidity_dht11",
        "value": 30,
    },
    {
        "id": 3,
        "description": "espclient2",
        "sensor_name": "ultrasonic_sensor",
        "value": 20,
    },
]

def _get_sensor(id):
    return [sensor for sensor in sensors if sensor['id'] == id]

def _record_exists(sensor_name):
    return [
        sensor for sensor in sensors if sensor["sensor_name"] == sensor_name
    ]

@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': NOT_FOUND}), 404)

@app.errorhandler(400)
def bad_request(error):
    return make_response(jsonify({'error': BAD_REQUEST}), 400)

@app.route('/api/sensors', methods=['GET'])
def get_sensors():
    return jsonify({'sensors': sensors})

@app.route('/api/sensors/<int:id>', methods=['GET'])
def get_sensor(id):
    sensor = _get_sensor(id)
    if not sensor:
        abort(404)
    return jsonify({'sensors': sensor})

@app.route('/api/sensors', methods=['POST'])
def create_sensor():
    if not request.json or 'description' not in request.json or 'sensor_name' not in request.json or 'value' not in request.json:
        abort(400)
    sensor_id = sensors[-1].get("id") + 1
    description = request.json.get('description')
    sensor_name = request.json.get('sensor_name')
    if _record_exists(sensor_name):
        abort(400)
    value = request.json.get('value')
    if type(value) is not int:
        abort(400)
    sensor = {
            "id": sensor_id,
            "description": description,
            "sensor_name": sensor_name,
            "value": value
    }
    sensors.append(sensor)
    return jsonify({'sensor': sensor}), 201


@app.route('/api/sensors/<int:id>', methods=['PUT'])
def update_sensor(id):
    sensor = _get_sensor(id)
    if len(sensor) == 0:
        abort(404)
    if not request.json:
        abort(400)
    description = request.json.get('description', sensor[0]['description'])
    sensor_name = request.json.get('sensor_name', sensor[0]['sensor_name'])
    value = request.json.get('value', sensor[0]['value'])
    if type(value) is not int:
        abort(400)
    sensor[0]['description'] = description
    sensor[0]['sensor_name'] = sensor_name
    sensor[0]['value'] = value
    return jsonify({'sensor': sensor[0]}), 200


@app.route('/api/sensors/<int:id>', methods=['DELETE'])
def delete_sensor(id):
    sensor = _get_sensor(id)
    if len(sensor) == 0:
        abort(404)
    sensors.remove(sensor[0])
    return jsonify({}), 204

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

