from __future__ import print_function
from chain.core.models import ScalarData
from django.utils import timezone
from django.db import models
from datetime import datetime
from chain.influx_client import InfluxClient, HTTP_STATUS_SUCCESSFUL_WRITE
from chain.core.resources import influx_client
from sys import stdout

# needs to be run from the manage.py shell context. Entry point is
# `migrate_data`

BATCH_SIZE = 10000
FIRST_TIMESTAMP = datetime.utcfromtimestamp(
    float(1481811788574987776)/1e9).replace(tzinfo=timezone.utc)


def migrate_data(offset, limit=float('inf')):
    '''Returns objects between offset and offset+limit'''
    #queryset = ScalarData.objects.filter(
    #    timestamp__lt=FIRST_TIMESTAMP.isoformat())
    #print('Calculating min and max IDs...')
    #min_max = queryset.aggregate(min=models.Min('id'), max=models.Max('id'))
    #min_id = min_max['min']
    #max_id = min_max['max']
    min_id = 0
    max_id = 1068348868
    print('Got min ID {0} and max ID {0}'.format(min_id, max_id))
    moved = 0
    for i in range(min_id, max_id+1, BATCH_SIZE):
        print('Start moving objects[{0}:{1}]...'.format(
              i, i+BATCH_SIZE), end='')
        stdout.flush()
        moved_count = post_points(ScalarData.objects.filter(id__range=(i, i+BATCH_SIZE-1)))
        print('Moved {0} objects'.format(moved_count))
        stdout.flush()
        moved += moved_count
        if moved >= limit:
            break


def post_points(queryset):
    """Performs the Postgres query and posts the data to influx. Returns the
    number of data points copied"""
    data = ''
    datacount = 0
    for point in queryset:
        timestamp = InfluxClient.convert_timestamp(point.timestamp)
        data += '{0},sensor_id={1} value={2} {3}\n'.format(
            influx_client._measurement,
            point.sensor_id,
            point.value,
            timestamp)
        datacount += 1
    response = influx_client.request('POST',
                                     influx_client._url + '/write',
                                     {'db': influx_client._database},
                                     data)
    # print the timestamp of the last point so we get some sense of where we
    # are
    print("[{0}] ".format(point.timestamp), end='')
    stdout.flush()
    if response.status_code != HTTP_STATUS_SUCCESSFUL_WRITE:
        raise RuntimeError("Influx returned status {0}".format(
            response.status_code))
    return datacount