from django.core.management.base import BaseCommand, CommandError
from django.db import transaction, IntegrityError
from django.utils import timezone
from datavis.models import *
from django.contrib.auth.models import User

import datetime

class Command(BaseCommand):
    help = "Initialize database with test data"

    def add_arguments(self, parser):
        # parser.add_argument("part", nargs="+", type=int)
        pass

    @transaction.atomic
    def handle(self, *args, **options):
        try:
            with transaction.atomic():
                try:
                    self.stdout.write(
                        self.style.NOTICE("Adding base data")
                    )
                    self.add_base_data()
                except Exception as e:
                    raise CommandError("Failed to add base data", e)
                try:
                    self.stdout.write(
                        self.style.NOTICE("Adding Robot Hands data")
                    )
                    self.add_robot_hands_groups()
                except Exception as e:
                    raise CommandError("Failed to add robot hands group", e)
                try:
                    self.stdout.write(
                        self.style.NOTICE("Adding demo site")
                    )
                    self.add_demo_site()
                except Exception as e:
                    raise CommandError("Failed to add demo turkey site", e)
                try:
                    self.stdout.write(
                        self.style.NOTICE("Adding virtual site")
                    )
                    self.add_virtual_site()
                except Exception as e:
                    raise CommandError("Failed to add virtual site data", e)
        except IntegrityError:
            raise CommandError("Failed to add virtual site data", e)
        self.stdout.write(
            self.style.SUCCESS("Successfully generated sample data")
        )

    def add_base_data(self):
        group_types = [
            "Site",
            "Windrow",
            "Temperature Site"
        ]

        author = User.objects.all()[0]

        for group_type_name in group_types:
            group_type = GroupType()
            group_type.author = author
            group_type.name = group_type_name
            group_type.save()

    def add_robot_hands_groups(self):
        group_types = GroupType.objects.all()

        author = User.objects.all()[0]

        """
          Site: "Wisconsin Turkey"
				- [ ] Windrows: 2 Windrows
					- [ ] 10 temperature sites each
        """
        robot_hands = Group()
        robot_hands.author = author
        robot_hands.name = "Robot Hands"
        robot_hands.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = robot_hands
        group_type.type = group_types.get(name="Site")
        group_type.save()

        incomplete_probes = Group()
        incomplete_probes.author = author
        incomplete_probes.name = "Incomplete Probes"
        incomplete_probes.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = incomplete_probes
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = robot_hands
        group_parent.child = incomplete_probes
        group_parent.save()

        incomplete_base_stations = Group()
        incomplete_base_stations.author = author
        incomplete_base_stations.name = "Incomplete Base Stations"
        incomplete_base_stations.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = incomplete_base_stations
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = robot_hands
        group_parent.child = incomplete_base_stations
        group_parent.save()

        complete_probes = Group()
        complete_probes.author = author
        complete_probes.name = "Probes Ready To Deploy"
        complete_probes.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = complete_probes
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = robot_hands
        group_parent.child = complete_probes
        group_parent.save()

        complete_base_stations = Group()
        complete_base_stations.author = author
        complete_base_stations.name = "Base Stations Ready To Deploy"
        complete_base_stations.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = complete_base_stations
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = robot_hands
        group_parent.child = complete_base_stations
        group_parent.save()

    def add_demo_site(self):
        group_types = GroupType.objects.all()
        author = User.objects.all()[0]

        demo_site = Group()
        demo_site.author = author
        demo_site.name = "Wisconsin Turkey"
        demo_site.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = demo_site
        group_type.type = group_types.get(name="Site")
        group_type.save()

        windrow_1 = Group()
        windrow_1.author = author
        windrow_1.name = "Windrow 1"
        windrow_1.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = windrow_1
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = demo_site
        group_parent.child = windrow_1
        group_parent.save()

        windrow_2 = Group()
        windrow_2.author = author
        windrow_2.name = "Windrow 2"
        windrow_2.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = windrow_2
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = demo_site
        group_parent.child = windrow_1
        group_parent.save()

        for i in range(10):
            temperature_site = Group()
            temperature_site.author = author
            temperature_site.name = f"{windrow_1.name} - Site {i+1}"
            temperature_site.save()
            group_type = Group2Type()
            group_type.author = author
            group_type.group = temperature_site
            group_type.type = group_types.get(name="Temperature Site")
            group_type.save()
            group_parent = GroupParent()
            group_parent.author = author
            group_parent.parent = windrow_1
            group_parent.child = temperature_site
            group_parent.save()

        for i in range(10):
            temperature_site = Group()
            temperature_site.author = author
            temperature_site.name = f"{windrow_2.name} - Site {i+1}"
            temperature_site.save()
            group_type = Group2Type()
            group_type.author = author
            group_type.group = temperature_site
            group_type.type = group_types.get(name="Temperature Site")
            group_type.save()
            group_parent = GroupParent()
            group_parent.author = author
            group_parent.parent = windrow_2
            group_parent.child = temperature_site
            group_parent.save()

    def add_virtual_site(self):
        group_types = GroupType.objects.all()
        author = User.objects.all()[0]
        """
        10 virtual nodes
			- [ ] 1 virtual base station
			- [ ] Virtual Site
			- [ ] Virtual Windrow
			- [ ] 10 Virtual temperature sites
			- [ ] 2 weeks of sample data for all nodes
        """
        virtual_site = Group()
        virtual_site.author = author
        virtual_site.name = "Virtual Site"
        virtual_site.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = virtual_site
        group_type.type = group_types.get(name="Site")
        group_type.save()

        windrow_1 = Group()
        windrow_1.author = author
        windrow_1.name = "Windrow 1"
        windrow_1.save()
        group_type = Group2Type()
        group_type.author = author
        group_type.group = windrow_1
        group_type.type = group_types.get(name="Windrow")
        group_type.save()
        group_parent = GroupParent()
        group_parent.author = author
        group_parent.parent = virtual_site
        group_parent.child = windrow_1
        group_parent.save()

        temperature_sites: list[Group] = []
        for i in range(10):
            temperature_site = Group()
            temperature_site.author = author
            temperature_site.name = f"{windrow_1.name} - Site {i+1}"
            temperature_site.save()
            temperature_sites.append(temperature_site)
            group_type = Group2Type()
            group_type.author = author
            group_type.group = temperature_site
            group_type.type = group_types.get(name="Temperature Site")
            group_type.save()
            group_parent = GroupParent()
            group_parent.author = author
            group_parent.parent = windrow_1
            group_parent.child = temperature_site
            group_parent.save()

        virtual_base_station = Node()
        virtual_base_station.author = author
        virtual_base_station.friendly_name = "Virtual Base Station 1"
        virtual_base_station.hardware_id = "1"
        virtual_base_station.save()
        node_group = Node2Group()
        node_group.author = author
        node_group.node = virtual_base_station
        node_group.group = windrow_1
        node_group.save()

        NUM_VIRTUAL_NODES = 10
        created_nodes: list[Node] = []
        for i in range(NUM_VIRTUAL_NODES):
            virtual_node = Node()
            virtual_node.author = author
            virtual_node.friendly_name = f"Virtual Probe {i + 1}"
            virtual_node.save()
            created_nodes.append(virtual_node)

            node_group = Node2Group()
            node_group.author = author
            node_group.node = virtual_node
            node_group.group = temperature_sites[i]
            node_group.save()

        SAMPLES_PER_DAY = 4
        NUMBER_OF_DAYS = 14
        for i in range(SAMPLES_PER_DAY * NUMBER_OF_DAYS):
            for node_index in range(NUM_VIRTUAL_NODES):
                measurement = Measurement()
                measurement.source_node = created_nodes[node_index]
                measurement.reporting_node = virtual_base_station
                measurement.associated_group = temperature_sites[node_index]
                # Every 6 hours
                measurement.collection_time = timezone.now() + datetime.timedelta(seconds=6 * 3600 * i)
                # Slight offset
                measurement.server_received_time = timezone.now() + datetime.timedelta(seconds=6.25 * 3600 * i)
                measurement.probe_temperature = 1.0
                measurement.temperature_18_inch = 1.0
                measurement.temperature_36_inch = 1.0
                measurement.ambient_temperature = 1.0
                measurement.device_temperature = 1.0
                measurement.barometric_pressure = 1.0
                measurement.relative_humidity = 1.0
                measurement.accelerometer_x = 1.0
                measurement.accelerometer_y = 1.0
                measurement.accelerometer_z = 1.0
                measurement.battery_charge_percent = 50.0
                measurement.battery_voltage = 3.0
                measurement.remaining_battery_capacity = 0.5
                measurement.save()