import os
from functools import reduce

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wnsq.settings")
from panelists.models import Panelist
from devices.models import Olfactometer
from django.db import transaction
from users.models import WinoseUser
from measurements.models import Measurement, MeasurementRound, SingleRoundResult
from samples.models import Sample
from .generators import *
from math import sqrt

transaction.set_autocommit(False)

olfi_op = WinoseUser.objects.all()

olfi = Olfactometer.objects.first()
calib = olfi.calibration

# grab a panel, force eval here to save up some time
allp = list(Panelist.objects.all())

all_buta = list(Sample.objects.filter(cylinder__substance='B'))
all_ref = list(Sample.objects.filter(cylinder__isnull=False))
all_sample = list(Sample.objects.all())

SingleRoundResult.objects.all().delete()
MeasurementRound.objects.all().delete()
Measurement.objects.all().delete()

measure_start = random_date_time_past()

max_mes = 400

for x in range(max_mes):

    m = Measurement()
    m.used_method = 1
    m.presentation_time = 2200
    m.sample = random.choice(all_sample)
    m.location = 'Lab Room 2'
    m.temperature = 22.0
    m.olfactometer = olfi
    m.standard_identifier = 1
    m.calibration = calib
    m.compliant_result = True
    m.save()

    panel = random.sample(allp, random.randint(5, 6))

    single_ites = list()
    for le_round in range(random.randint(3, 5)):
        current_round = MeasurementRound()
        current_round.operator = random.choice(olfi_op)
        current_round.is_included = le_round > 0
        current_round.number = le_round + 1
        current_round.comments = 'now that was a fancy round...'
        current_round.reference_measurement = m

        msa = measure_start + timedelta(minutes=le_round * (le_round + 1))
        mfa = msa + timedelta(minutes=2)
        assert (msa.tzinfo is not None and msa.tzinfo.utcoffset(msa) is not None)
        assert (mfa.tzinfo is not None and mfa.tzinfo.utcoffset(mfa) is not None)
        current_round.started_at = msa
        current_round.finished_at = mfa
        dil_series = [4096, 2048, 1024, 512, 256]
        current_round.series = ' '.join(str(x) for x in dil_series)

        # current_round.save()
        m.rounds.add(current_round)

        # note that this fake measurement stuff here only works because
        # there are no blanks in the series
        for p in panel:
            rsr = SingleRoundResult()
            rsr.delta_z = -2.0 + random.random() * 4.0

            rsr.panelist = p
            rsr.round = current_round
            if random.random() < 0.2:
                starts_to_press = 1
            else:
                starts_to_press = random.randint(2, 3)
            rpList = ''
            for step in range(len(dil_series)):
                if step < starts_to_press or dil_series[step] == 0:
                    rpList += '0,0 '
                else:
                    rpList += '1,0 '
            rsr.ite = sqrt(dil_series[starts_to_press] * dil_series[starts_to_press - 1])

            if current_round.is_included:
                single_ites.append(rsr.ite)
            rsr.replies = rpList

            current_round.results.add(rsr)

    import operator

    tite = pow(reduce(operator.mul, single_ites, 1), 1.0 / len(single_ites))

    # m.result = tite * m.sample.total_dilution
    m.analysis_result = tite
    m.finished_at = m.rounds.order_by('-finished_at').first().finished_at
    m.save()
    # mess it up every now and then
    # if random.random() > 0.9:
    #     m.result = None

    # need to create stuff in order, else this fucks up the history
    measure_start = measure_start + timedelta(days=4)

transaction.commit()
transaction.set_autocommit(True)
