#
#    Khan Academy Exercises for Course Builder
#
#    Copy Right (C) 2013 Pavel Simakov (pavel@vokamis.com)
#    https://github.com/psimakov/khan-exercises-coursebuilder
#
#    This library is free software; you can redistribute it and/or
#    modify it under the terms of the GNU Lesser General Public
#    License as published by the Free Software Foundation; either
#    version 2.1 of the License, or (at your option) any later version.
#
#    This library 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
#    Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
#    USA
#

"""Khan Academy exercises for Course Builder.


This extension lets you host Khan Academy exercises in your Course Builder
course. These exercises make learning complex subjects fun and they are free to
everyone! However, the framework is very complex; it's difficult to embed its
exercises into another web site. We made framework changes, which make it
easier to embed the exercises and collect the exercise results right in your
Course Builder course.

Here is how to install, activate and use this module:
    - download Course Builder (1.4.1)
    - download this package
    - copy all files in this package into /modules/khanex/... folder of your
      Course Builder application folder
    - edit main.app of your application
        - add new import where all other modules are imported:
          import modules.khanex.khanex
        - enable the module, where all other modules are enabled:
          modules.khanex.khanex.register_module().enable()
    - restart your local development sever or re-deploy your application
    - edit a lesson using visual editor; you should be able to add a new
      component type "Khan Academy Exercise"
    - the component editor should show a list of all exercises available in a
      dropdown list; there should be over 400 exercises listed here
    - pick one exercise, save the component configuration
    - add empty exercise definition var activity = []; uncheck 'Activity Listed'
    - save  the lesson
    - enable gcb_can_persist_activity_events and gcb_can_persist_page_events
    - preview the lesson
    - click "Check Answer" and see how data is recorded in the datastore
      EventEntity table with a namespace appropriate for your course
    - this is it!

This work is based on my other project, which brings Khan Academy exercises to
WordPress. You can learn more about it here:
  http://www.softwaresecretweapons.com/jspwiki/khan-exercises

Here are the things I found difficult to do while completing this integration:
    - if a unit is marked completed in a progress tracking system, and author
      adds new unit - the progress indicator is now wrong and must be recomputed
      to account for a new added unit
    - why don't we circles next to the lessons of the left nav. of the unit?
    - how does a tag/module know what unit/lesson is being shown now? we need to
      pass some kind of course_context into tag/module... how much of view model
      do we expose to the tag/module? can a tag instance introspect what is
      above and below it in the rendering context?
    - we do show "Loading..." indicator while exercise JavaScript loads up,
      but it is dismissed too early now
    - tag.render() method must give access to the handler, ideally before the
      rendering phase begins
    - our model for tracking progress assumes lesson is an atomic thing; so
      if one has 3 exercises on one lesson page, only one marker is used and
      it is not possible to track progress of individual exercises; ideally any
      container should automatically support progress tracking for its children

We need to improve these over time.

Good luck!
"""

__author__ = 'Pavel Simakov (pavel@vokamis.com)'

import cgi
import os
import urllib2
import urlparse
from xml.etree import cElementTree
import zipfile

from common import schema_fields
from common import tags
from controllers import sites
from controllers import utils
from models.config import ConfigProperty
from models.counters import PerfCounter
from models import custom_modules
from models import models
from models import transforms


ATTEMPT_COUNT = PerfCounter(
    'gcb-khanex-attempt-count',
    'A number of attempts made by all users on all exercises.')

WHITELISTED_EXERCISES = ConfigProperty(
    '_khanex_whitelisted', str, (
        'A white-listed exercises that can be show to students. If this list '
        'is empty, all exercises are available.'),
    default_value='', multiline=True)

ZIP_FILE = os.path.join(os.path.dirname(__file__), 'khan-exercises.zip')
EXERCISE_BASE = 'khan-exercises/khan-exercises/exercises/'

EXERCISE_HTML_PAGE_RAW = (
    """<!DOCTYPE html>
<html">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<head>
<body>
<div style="width: 100%; margin: 0px;">
    <style>
        /* hide optional elements */
        div.exercises-header {
            display: none;
        }
        div#extras{
            display: none;
        }

        /* customize color scheme to match */
        article.exercises-content {
            background-color: transparent;
        }
        div#workarea {
            background-color: white;
            padding: 8px;
            margin-bottom: 8px;
        }
    </style>
    <header style="display: none;" />
    <div id="container" class="single-exercise visited-no-recolor"
            style="overflow: hidden;">
        <article class="exercises-content clearfix">
        <div class="exercises-header"><h2 class="section-headline">
                <div class="topic-exercise-badge">&nbsp;</div>
                <span class="practice-exercise-topic-context">Practicing</span>
        </h2></div>
        <div class="exercises-body">
            <div class="exercises-stack">&nbsp;</div>
            <div class="exercises-card current-card">
                <div class="current-card-container card-type-problem">
                    <div class="current-card-container-inner vertical-shadow">
                        <div class="current-card-contents">
                        </div>
                    </div>
                    <div id="extras" class="single-exercise">
                        <ul>
                            <li>
                                <a id="scratchpad-show" href style>
                                    Show scratchpad</a>
                                <span id="scratchpad-not-available"
                                        style="display: none;">
                                    Scratchpad not available</span>
                            </li>
                            <li class="debug-mode">
                                <a href="?debug">Debug mode</a>
                            </li>
                            <li>
                                <a id="problem-permalink" href>
                                    Problem permalink</a>
                            </li>
                        </ul>