<commit_before># -*- coding: utf-8 -*-

# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
import six
import logging
import uuid
from django.core import mail

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.forms import (
    ModelForm,
    ModelChoiceField,
    ModelMultipleChoiceField
)
from django.core.cache import cache
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from django.views.generic import (
    ListView,
    DeleteView,
    CreateView,
    UpdateView
)

from wger.manager.models import WorkoutLog
from wger.exercises.models import (
    Exercise,
    Muscle,
    ExerciseCategory
)
from wger.exercises.widgets import MuscleTranslatedSelectMultiple
from wger.utils.generic_views import (
    WgerFormMixin,
    WgerDeleteMixin,
    WgerPermissionMixin
)
from wger.utils.language import load_language, load_item_languages
from wger.utils.cache import cache_mapper
from wger.utils.widgets import TranslatedSelect, TranslatedSelectMultiple
from wger.config.models import LanguageConfig
from wger.weight.helpers import process_log_entries


logger = logging.getLogger(__name__)


class ExerciseListView(WgerPermissionMixin, ListView):
    '''
    Generic view to list all exercises
    '''

    model = Exercise
    template_name = 'exercise/overview.html'
    context_object_name = 'exercises'

    def get_queryset(self):
        '''
        Filter to only active exercises in the configured languages
        '''
        languages = load_item_languages(LanguageConfig.SHOW_ITEM_EXERCISES)
        return Exercise.objects.accepted() \
            .filter(language__in=languages) \
            .order_by('category__id') \
            .select_related()

    def get_context_data(self, **kwargs):
        '''
        Pass additional data to the template
        '''
        context = super(ExerciseListView, self).get_context_data(**kwargs)
        context['show_shariff'] = True
        return context


def view(request, id, slug=None):
    '''
    Detail view for an exercise
    '''

    template_data = {}
    template_data['comment_edit'] = False
    template_data['show_shariff'] = True

    # Load the exercise itself
    exercise = cache.get(cache_mapper.get_exercise_key(int(id)))
    if not exercise:
        exercise = get_object_or_404(Exercise, pk=id)
        cache.set(cache_mapper.get_exercise_key(exercise), exercise)

    template_data['exercise'] = exercise

    # Create the backgrounds that show what muscles the exercise works on
    backgrounds = cache.get(cache_mapper.get_exercise_muscle_bg_key(int(id)))
    if not backgrounds:
        backgrounds_back = []
        backgrounds_front = []

        for muscle in exercise.muscles.all():
            if muscle.is_front:
                backgrounds_front.append('images/muscles/main/muscle-%s.svg' % muscle.id)
            else:
                backgrounds_back.append('images/muscles/main/muscle-%s.svg' % muscle.id)

        for muscle in exercise.muscles_secondary.all():
            if muscle.is_front:
                backgrounds_front.append('images/muscles/secondary/muscle-%s.svg' % muscle.id)
            else:
                backgrounds_back.append('images/muscles/secondary/muscle-%s.svg' % muscle.id)

        # Append the "main" background, with the silhouette of the human body
        # This has to happen as the last step, so it is rendered behind the muscles.
        backgrounds_front.append('images/muscles/muscular_system_front.svg')
        backgrounds_back.append('images/muscles/muscular_system_back.svg')
        backgrounds = (backgrounds_front, backgrounds_back)

        cache.set(cache_mapper.get_exercise_muscle_bg_key(int(id)),
                  (backgrounds_front, backgrounds_back))

    template_data['muscle_backgrounds_front'] = backgrounds[0]
    template_data['muscle_backgrounds_back'] = backgrounds[1]

    # If the user is logged in, load the log and prepare the entries for
    # rendering in the D3 chart
    entry_log = []
    chart_data = []
    if request.user.is_authenticated():
        logs = WorkoutLog.objects.filter(user=request.user, exercise=exercise)
        entry_log, chart_data = process_log_entries(logs)

    template_data['logs'] = entry_log
    template_data['json'] = chart_data
    template_data['svg_uuid'] = str(uuid.uuid4())
    template_data['reps'] = _("Reps")

    return render(request, 'exercise/view.html', template_data)


class ExercisesEditAddView(WgerFormMixin):
    '''
    Generic view to subclass from for exercise adding and editing, since they
    share all this settings
    '''
    model = Exercise
    sidebar = 'exercise/form.html'
    title = ugettext_lazy('Add exercise')
    custom_js = 'init_tinymce();'
    clean_html = ('description', )

    def get_form_class(self):

        # Define the exercise form here because only at this point during the request
        # have we access to the currently used language. In other places Django defaults
        # to 'en-us'.
        class ExerciseForm(ModelForm):
            category = ModelChoiceField(queryset=ExerciseCategory.objects.all(),
                                        widget=TranslatedSelect())
            muscles = ModelMultipleChoiceField(queryset=Muscle.objects.all(),
                                               widget=MuscleTranslatedSelectMultiple(),
                                               required=False)

            muscles_secondary = ModelMultipleChoiceField(queryset=Muscle.objects.all(),
                                                         widget=MuscleTranslatedSelectMultiple(),
                                                         required=False)

            class Meta:
                model = Exercise
                widgets = {'equipment': TranslatedSelectMultiple()}
                fields = ['name',
                          'category',
                          'description',
                          'muscles',
                          'muscles_secondary',
                          'equipment',
                          'license',
                          'license_author']

            class Media:
                js = ('wger/core/static/bower_components/tinymce/tinymce.min.js',)

        return ExerciseForm<commit_msg>Fix path to tinyMCE path<commit_after># -*- coding: utf-8 -*-

# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
import six
import logging
import uuid
from django.core import mail

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.forms import (
    ModelForm,
    ModelChoiceField,
    ModelMultipleChoiceField
)
from django.core.cache import cache
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from django.views.generic import (
    ListView,
    DeleteView,
    CreateView,
    UpdateView
)

from wger.manager.models import WorkoutLog
from wger.exercises.models import (
    Exercise,
    Muscle,
    ExerciseCategory
)
from wger.exercises.widgets import MuscleTranslatedSelectMultiple
from wger.utils.generic_views import (
    WgerFormMixin,
    WgerDeleteMixin,
    WgerPermissionMixin
)
from wger.utils.language import load_language, load_item_languages
from wger.utils.cache import cache_mapper
from wger.utils.widgets import TranslatedSelect, TranslatedSelectMultiple
from wger.config.models import LanguageConfig
from wger.weight.helpers import process_log_entries


logger = logging.getLogger(__name__)


class ExerciseListView(WgerPermissionMixin, ListView):
    '''
    Generic view to list all exercises
    '''

    model = Exercise
    template_name = 'exercise/overview.html'
    context_object_name = 'exercises'

    def get_queryset(self):
        '''
        Filter to only active exercises in the configured languages
        '''
        languages = load_item_languages(LanguageConfig.SHOW_ITEM_EXERCISES)
        return Exercise.objects.accepted() \
            .filter(language__in=languages) \
            .order_by('category__id') \
            .select_related()

    def get_context_data(self, **kwargs):
        '''
        Pass additional data to the template
        '''
        context = super(ExerciseListView, self).get_context_data(**kwargs)
        context['show_shariff'] = True
        return context


def view(request, id, slug=None):
    '''
    Detail view for an exercise
    '''

    template_data = {}
    template_data['comment_edit'] = False
    template_data['show_shariff'] = True

    # Load the exercise itself
    exercise = cache.get(cache_mapper.get_exercise_key(int(id)))
    if not exercise:
        exercise = get_object_or_404(Exercise, pk=id)
        cache.set(cache_mapper.get_exercise_key(exercise), exercise)

    template_data['exercise'] = exercise

    # Create the backgrounds that show what muscles the exercise works on
    backgrounds = cache.get(cache_mapper.get_exercise_muscle_bg_key(int(id)))
    if not backgrounds:
        backgrounds_back = []
        backgrounds_front = []

        for muscle in exercise.muscles.all():
            if muscle.is_front:
                backgrounds_front.append('images/muscles/main/muscle-%s.svg' % muscle.id)
            else:
                backgrounds_back.append('images/muscles/main/muscle-%s.svg' % muscle.id)

        for muscle in exercise.muscles_secondary.all():
            if muscle.is_front:
                backgrounds_front.append('images/muscles/secondary/muscle-%s.svg' % muscle.id)
            else:
                backgrounds_back.append('images/muscles/secondary/muscle-%s.svg' % muscle.id)

        # Append the "main" background, with the silhouette of the human body
        # This has to happen as the last step, so it is rendered behind the muscles.
        backgrounds_front.append('images/muscles/muscular_system_front.svg')
        backgrounds_back.append('images/muscles/muscular_system_back.svg')
        backgrounds = (backgrounds_front, backgrounds_back)

        cache.set(cache_mapper.get_exercise_muscle_bg_key(int(id)),
                  (backgrounds_front, backgrounds_back))

    template_data['muscle_backgrounds_front'] = backgrounds[0]
    template_data['muscle_backgrounds_back'] = backgrounds[1]

    # If the user is logged in, load the log and prepare the entries for
    # rendering in the D3 chart
    entry_log = []
    chart_data = []
    if request.user.is_authenticated():
        logs = WorkoutLog.objects.filter(user=request.user, exercise=exercise)
        entry_log, chart_data = process_log_entries(logs)

    template_data['logs'] = entry_log
    template_data['json'] = chart_data
    template_data['svg_uuid'] = str(uuid.uuid4())
    template_data['reps'] = _("Reps")

    return render(request, 'exercise/view.html', template_data)


class ExercisesEditAddView(WgerFormMixin):
    '''
    Generic view to subclass from for exercise adding and editing, since they
    share all this settings
    '''
    model = Exercise
    sidebar = 'exercise/form.html'
    title = ugettext_lazy('Add exercise')
    custom_js = 'init_tinymce();'
    clean_html = ('description', )

    def get_form_class(self):

        # Define the exercise form here because only at this point during the request
        # have we access to the currently used language. In other places Django defaults
        # to 'en-us'.
        class ExerciseForm(ModelForm):
            category = ModelChoiceField(queryset=ExerciseCategory.objects.all(),
                                        widget=TranslatedSelect())
            muscles = ModelMultipleChoiceField(queryset=Muscle.objects.all(),
                                               widget=MuscleTranslatedSelectMultiple(),
                                               required=False)

            muscles_secondary = ModelMultipleChoiceField(queryset=Muscle.objects.all(),
                                                         widget=MuscleTranslatedSelectMultiple(),
                                                         required=False)

            class Meta:
                model = Exercise
                widgets = {'equipment': TranslatedSelectMultiple()}
                fields = ['name',
                          'category',
                          'description',
                          'muscles',
                          'muscles_secondary',
                          'equipment',
                          'license',
                          'license_author']

            class Media:
                js = ('/static/bower_components/tinymce/tinymce.min.js',)

        return ExerciseForm
{'fraction_non_alphanumeric': 0.07962807606263982, 'fraction_numerical': 0.0016778523489932886, 'mean_word_length': 2.6566973415132926, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6867769', 'n_tokens_mistral': 3881, 'n_tokens_neox': 3716, 'n_words': 1013}