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 django.core.files import File
from django.utils.six import BytesIO

from PIL import Image
from io import StringIO


def create_image(storage, filename, size=(100, 100), image_mode='RGB', image_format='PNG'):
   """
   Generate a test image, returning the filename that it was saved as.

   If ``storage`` is ``None``, the BytesIO containing the image data
   will be passed instead.
   """
   data = BytesIO()
   Image.new(image_mode, size).save(data, image_format)
   data.seek(0)
   if not storage:
       return data
   image_file = ContentFile(data.read())
   return storage.save(filename, image_file)

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

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

        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()

        result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')

        self.wwater = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'water',
        )

#        self.comments = CommentFactory.create_batch(5,
#            user = self.u,
#            created = timezone.now,
#            workout = self.wwater)

        result = get_random_file(filename='rowers/tests/testdata/quiske_in_stroke.csv')

        self.winstroke = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'water',
        )

        result = get_random_file(filename='rowers/tests/testdata/erg1.csv')

        self.werg1 = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'rower',
        )

        result = get_random_file(filename='rowers/tests/testdata/erg2.csv')

        self.werg2 = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'rower',
        )

        result = get_random_file(filename='rowers/tests/testdata/erg2.csv')

        self.werg2copy = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'rower',
        )


        result = get_random_file(filename='rowers/tests/testdata/erg3.csv')

        self.werg3 = WorkoutFactory(user=self.r,
                                     csvfilename=result['filename'],
                                     starttime=result['starttime'],
                                     startdatetime=result['startdatetime'],
                                     duration=result['duration'],
                                     distance=result['totaldist'],
                                     workouttype = 'rower',
        )

    def tearDown(self):
        pass

    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('rowers.middleware.myqueue')
    def test_forcecurve(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
                        mocked_myqueue):
        login = self.c.login(username=self.u.username, password=self.password)
        self.assertTrue(login)

        url  = reverse('workout_forcecurve_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'workstrokesonly': True
            }

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

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

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

        d1 = self.werg1.date-datetime.timedelta(days=2)
        d2 = self.werg2.date+datetime.timedelta(days=2)

        date_form_data = {
            'startdate': d1.strftime('%Y-%m%d'),
            'enddate': d2.strftime('%Y-%m%d')
            }

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

        url  = reverse('workouts_join_view')

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

        expected_url = reverse('workouts_join_select')
        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,
                             target_status_code=200)

        form_data = {
            'workout_name': 'joined',
            'set_private': False,
            'workouts': [str(self.werg1.id),str(self.werg2.id),str(self.werg3.id)],
            }

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

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

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

        expected_url = reverse(self.r.defaultlandingpage,
                               kwargs = {
                                   'id':encoder.encode_hex(12)
                                   })

        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,target_status_code=200)

    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('rowers.middleware.myqueue')
    def test_compares(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
                      mocked_myqueue):
        login = self.c.login(username=self.u.username, password=self.password)
        self.assertTrue(login)


        session = self.c.session
        session['ids'] = [self.werg1.id,self.werg2.id]
        session.save()

        response = self.c.get('/')
        url = reverse('multi_compare_view',kwargs={
            'userid':self.u.id,
            'id':encoder.encode_hex(self.werg1.id),
        })
        print(url)

        form_data = {
            'xparam':'time',
            'yparam':'power',
            'plottype':'line',
            'teamid': '',
            }


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

        session['plottype'] = 'scatter'
        session['xparam'] = 'time'
        session['yparam'] = 'hr'

        session.save()

        response = self.c.get('/')

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

    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('rowers.weather.requests.get', side_effect=mocked_requests)
    def test_waterworkout_view(self,
                               mocked_sqlalchemy, mocked_getsmallrowdata_db, mocked_requests):
        login = self.c.login(username=self.u.username, password=self.password)
        self.assertTrue(login)

        url  = reverse('workout_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        url = reverse('workout_downloadmetar_view',kwargs={
            'id': encoder.encode_hex(self.wwater.id),
            'airportcode': 'LKHO'
            }
            )

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

        url = reverse('workout_downloadwind_view',kwargs={
            'id': encoder.encode_hex(self.wwater.id),
            }
            )

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

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


        url = reverse('workout_smoothenpace_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        expected_url = reverse(self.r.defaultlandingpage,
                               kwargs = {
                                   'id':encoder.encode_hex(self.wwater.id)
                                   }
                               )

        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,target_status_code=200)

        url = reverse('workout_undo_smoothenpace_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        expected_url = reverse(self.r.defaultlandingpage,
                               kwargs = {
                                   'id':encoder.encode_hex(self.wwater.id)
                                   }
                               )

        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,target_status_code=200)


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


        url = reverse('workout_wind_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'dist1':1000,
            'dist2':2000,
            'vwind1':2.0,
            'vwind2':1.4,
            'windunit':'m',
            'winddirection1': 0,
            'winddirection2': 90,
            }

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

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

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


        url = reverse('workout_stream_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'dist1':1000,
            'dist2':2000,
            'stream1':2.0,
            'stream2':1.4,
            'streamunit':'m',
            }

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

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



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

        url = reverse('instroke_view',kwargs={'id':encoder.encode_hex(self.winstroke.id)})

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

        rowdata = rowingdata.rowingdata(csvfile=self.winstroke.csvfilename)
        instrokemetrics = rowdata.get_instroke_columns()

        self.assertTrue(len(instrokemetrics)>0)

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


        url = reverse('workout_otwsetpower_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'quick_calc':True,
            'boattype': '1x',
            'weightvalue': 75.0,
            }

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

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

        expected_url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,target_status_code=200)

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


        url = reverse('workout_comment_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'comment': faker.text()
            }

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

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

        url = reverse('workout_unsubscribe_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
        response = self.c.get(url)
        self.assertEqual(response.status_code,200)

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


        url = reverse('workout_map_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

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

        url  = reverse('workout_uploadimage_view',
                       kwargs={'id':encoder.encode_hex(self.werg1.id)})

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

        with open('rowers/tests/testdata/lofoten.jpg','rb') as screenshot_file:
            file_data = {'file':screenshot_file}
            form_data = {
                'file':screenshot_file,
            }

            #form = ImageForm(form_data, file_data)
            #if not form.is_valid():
            #    print form.errors
            #self.assertTrue(form.is_valid())

            response = self.c.post(url,form_data,format='multipart',follow=True)

            expected_url = reverse(self.r.defaultlandingpage,
                                   kwargs={'id':encoder.encode_hex(self.werg1.id)})

            self.assertRedirects(response,
                                 expected_url=expected_url,
                                 status_code=302,target_status_code=200)

    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.getsmallrowdata_db')
    @patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
    def test_workout_split(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
                           mocked_getrowdata_db):
        login = self.c.login(username=self.u.username, password=self.password)
        self.assertTrue(login)

        url  = reverse('workout_split_view',kwargs={'id':encoder.encode_hex(self.werg1.id)})

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

        form_data = {
            'splittime': '2:00',
            'splitmode': ['keep original','keep first','keep second']
            }

        form = WorkoutSplitForm(form_data)

        self.assertTrue(form.is_valid())

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

    @patch('rowers.dataprep.create_engine')
    @patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
    @patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_forfusion)
    def test_workout_fusion(self, mocked_sqlalchemy, mocked_getrowdata_db,
                            mocked_getsmallrowdata_db):
        login = self.c.login(username=self.u.username, password=self.password)
        self.assertTrue(login)

        url  = reverse('workout_fusion_view',
                       kwargs={'id1':encoder.encode_hex(self.werg2.id),
                               'id2':encoder.encode_hex(self.werg2copy.id)})


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

        form_data = {
            'posneg':'pos',
            'offset': datetime.timedelta(seconds=0),
            'columns': ['power','hr'
                        ]
            }

        form = FusionMetricChoiceForm(form_data,instance=self.werg2copy)

        self.assertTrue(form.is_valid())

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


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


        url = reverse('workout_summary_edit_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})

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

        form_data = {
            'intervalstring':'4x2min/1min',
            }

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

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

        form_data = {
            'powerorpace':'power',
            'value_pace':'2:23',
            'value_power':'200',
            'value_work':'400',
            'value_spm':'20',
            'activeminutesmin':'0',
            'activeminutesmax':'60',
            'savepowerpaceform':True,
            }

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

        form_data = {
            'savestringform':'4x2min/1min',
            }

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

        form_data = {
            'selector':'power',
            'power': 200,
            'pace': '2:30',
            'work': 400,
            'activeminutesmin':'0',
            'activeminutesmax': '60',
            }

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

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


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

        url = reverse('workout_delete',kwargs={'pk':self.wwater.id})

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

        post_data = {}

        response = self.c.post(url,follow=True)

        expected_url = reverse('workouts_view')

        self.assertRedirects(response,
                             expected_url=expected_url,
                             status_code=302,target_status_code=200)
