from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from .statements import *

nu = datetime.datetime.now()

from rowers.tasks import handle_getagegrouprecords

from rowers.utils import calculate_age

import rowers.dataprep as dataprep


@override_settings(TESTING=True)
class OTWCPChartTest(TestCase):
    def setUp(self):
        self.u = UserFactory()

        self.r = Rower.objects.create(user=self.u,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,sex='male',
                                      weightcategory='hwt',
                                      gdproptindate=timezone.now(),
                                      rowerplan='coach')

        r = self.u.rower
        age = calculate_age(r.birthdate)
        self.c = Client()
        self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
        self.factory = RequestFactory()
        self.password = faker.word()
        self.u.set_password(self.password)
        self.u.save()

        self.lastdate = datetime.date(year=1970,month=1,day=1)

        for filename in os.listdir(u'rowers/tests/testdata/otwcp'):
            a2 = 'rowers/tests/testdata/otwcp/temp/'+filename
            try:
                copy(u'rowers/tests/testdata/otwcp/'+filename,a2)
                row = rdata(a2)
                totaldist = row.df['cum_dist'].max()
                totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
                totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]


                hours = int(totaltime/3600.)
                minutes = int((totaltime - 3600.*hours)/60.)
                seconds = int(totaltime - 3600.*hours - 60.*minutes)
                tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))

                duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
                duration = datetime.time(hour=hours,minute=minutes,second=seconds)

                workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
                workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')

                w = Workout.objects.create(name=faker.word(),
                                           workouttype='water',
                                           user = self.r,
                                           starttime = workoutstarttime,
                                           date = workoutdate,
                                           duration = duration,
                                           distance = totaldist,
                                           csvfilename = a2,
                                           rankingpiece = True)
                w.save()

                if row.rowdatetime.date() > self.lastdate:
                    self.lastdate = row.rowdatetime.date()
            except:
                pass

    def tearDown(self):
        try:
            for filename in os.listdir('rowers/tests/testdata/otwcp/temp'):
                path = os.path.join('rowers/tests/testdata/otwcp/temp/',filename)
                if not os.path.isdir(path):
                    try:
                        os.remove(path)
                    except (IOError,FileNotFoundError,OSError):
                        pass
        except (IOError,FileNotFoundError,OSError):
            pass

    @patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_cpraw)
    @patch('rowers.dataprep.getcpdata_sql',side_effect=mocked_getcpdata_sql)
    def test_otwrankingpieces(self, mocked_cpraw,mocked_getcpdata_sql):
        workouts = Workout.objects.filter(workouttype='water',
                                          rankingpiece=True,user=self.r)

        delta, cpvalue, avgpower = dataprep.fetchcp(self.r,workouts)

    @patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_cpraw)
    @patch('rowers.dataprep.getcpdata_sql',side_effect=mocked_getcpdata_sql)
    def test_otwrankingpieces(self, mocked_cpraw,mocked_getcpdata_sql):
        login = self.c.login(username=self.u.username,password=self.password)
        self.assertTrue(login)

        url = '/rowers/otw-bests/'

        response = self.c.get(url)
        self.assertEqual(response.status_code, 200)


@override_settings(TESTING=True)
class CPChartTest(TestCase):
    def setUp(self):
        self.u = UserFactory()

        self.r = Rower.objects.create(user=self.u,
                                      birthdate=faker.profile()['birthdate'],
                                      gdproptin=True,surveydone=True,sex='male',
                                      weightcategory='hwt',
                                      gdproptindate=timezone.now(),
                                      rowerplan='coach')

        r = self.u.rower
        age = calculate_age(r.birthdate)
        self.c = Client()
        self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
        self.factory = RequestFactory()
        self.password = faker.word()
        self.u.set_password(self.password)
        self.u.save()

        recordsdf = pd.read_csv('rowers/tests/worldrecords.csv',encoding='utf-8')

        for i in recordsdf.index:
            record = C2WorldClassAgePerformance(
                name = recordsdf.loc[i,'name'],
                age = recordsdf.loc[i,'age'],
                distance = recordsdf.loc[i,'distance'],
                duration = recordsdf.loc[i,'duration'],
                power = recordsdf.loc[i,'power'],
                season = recordsdf.loc[i,'season'],
                sex = recordsdf.loc[i,'sex'],
                weightcategory = recordsdf.loc[i,'weightcategory'],
            )

            record.save()

        perfsdf = pd.read_csv('rowers/tests/testdata/calcageperformance.csv')

        r = self.u.rower

        for i in perfsdf.index:
            perf = CalcAgePerformance(
                age = age,
                duration = perfsdf.loc[i,'duration'],
               power = perfsdf.loc[i,'power'],
                sex = r.sex,
                weightcategory = r.weightcategory
                )
            perf.save()

    def tearDown(self):
        for workout in self.user_workouts:
            try:
                os.remove(workout.csvfilename)
            except (IOError, FileNotFoundError,OSError):
                pass

    def test_analytics_page(self):
        login = self.c.login(username=self.u.username,password=self.password)
        self.assertTrue(login)

        url = '/rowers/analysis/'

        response = self.c.get(url)
        self.assertEqual(response.status_code, 200)

    @patch('rowers.dataprep.create_engine')
    def test_addmanual(self, mocked_sqlalchemy):
        login = self.c.login(username=self.u.username,password=self.password)
        self.assertTrue(login)


        form_data = {
            'name': faker.word(),
            'date': nu.date(),
            'starttime': '10:01:43',
            'timezone': 'UTC',
            'duration': '00:02:00.0',
            'distance': 500,
            'workouttype': 'rower',
            'boattype': '1x',
            'weightcategory': 'hwt',
            'adaptiveclass': 'None',
            'notes': faker.text(),
            'rankingpiece': True,
            'duplicate': False,
            'avghr': '160',
            'avgpwr': 0,
            'avgspm': 40,
            }

        form = MetricsForm(form_data)
        self.assertTrue(form.is_valid())

        form = WorkoutForm(form_data)
        self.assertTrue(form.is_valid())


        url = '/rowers/workout/addmanual/'
        response = self.c.get(url)

        self.assertEqual(response.status_code,200)

        response = self.c.post(url, form_data, follow=True)
        self.assertEqual(response.status_code,200)

        workout_expected_id = 6

        self.assertRedirects(response,
                             expected_url='/rowers/workout/{id}/edit/'.format(
                                 id=encoder.encode_hex(workout_expected_id)),
                             status_code=302,target_status_code=200)

        # add some tests of complex form data (no hr, no spm, zero spm, etc)

    @patch('rowers.dataprepnodjango.create_engine')
    def test_agerecords(self, mock_sqlalchemy):
        #        update_records(url='rowers/tests/c2worldrecords.html',verbose=False)

        r = self.u.rower
        age = calculate_age(r.birthdate)

        wcdurations = []
        wcpower = []
        durations = [1,4,30,60]
        distances = [100,500,1000,2000,5000,6000,10000,21097,42195]

        df = pd.DataFrame(
            list(
                C2WorldClassAgePerformance.objects.filter(
                    sex=r.sex,
                    weightcategory=r.weightcategory
                ).values()
            )
        )

        jsondf = df.to_json()

        result = handle_getagegrouprecords(
            jsondf,distances,durations,age,r.sex,r.weightcategory)

        self.assertEqual(result,1)

        url = '/rowers/agegrouprecords/{sex}/{weightc}/2000m/'.format(
            sex = r.sex,
            weightc = r.weightcategory)

        print(url)

        response = self.c.get(url)
        self.assertEqual(response.status_code,200)


    @patch('rowers.dataprep.fetchcperg', side_effect = mocked_fetchcperg)
    @patch('rowers.dataprep.create_engine')
    def test_rankingpieces(self, mocked_fetchcperg, mocked_sqlalchemy):
        url = '/rowers/ote-bests2/'

        login = self.c.login(username=self.u.username,password=self.password)
        self.assertTrue(login)

        #        update_records(url='rowers/tests/c2worldrecords.html',verbose=False)

        form_data = {
            'name': faker.word(),
            'date': nu.date(),
            'timezone': 'UTC',
            'duration': '00:02:00.0',
            'starttime': '10:01:43',
            'distance': 500,
            'workouttype': 'rower',
            'boattype': '1x',
            'weightcategory': 'hwt',
            'adaptiveclass': 'None',
            'notes': faker.text(),
            'rankingpiece': True,
            'duplicate': False,
            'avghr': '160',
            'avgpwr': 0,
            'avgspm': 40,
            }

        url2 = '/rowers/workout/addmanual/'

        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        form_data['distance'] = 100
        form_data['duration'] = '00:00:18.5'

        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        form_data['distance'] = 2000
        form_data['duration'] = '00:06:56.5'
        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        form_data['distance'] = 5000
        form_data['duration'] = '00:20:48.0'
        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        form_data['distance'] = 6000
        form_data['duration'] = '00:22:17.6'
        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        form_data['distance'] = 10000
        form_data['duration'] = '00:38:16.5'
        response = self.c.post(url2, form_data, follow=True)
        self.assertEqual(response.status_code, 200)

        response = self.c.get(url)
        self.assertEqual(response.status_code, 200)
