#!/usr/bin/env python
# Licensed to Cloudera, Inc. under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  Cloudera, Inc. licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
try:
  import json
except ImportError:
  import simplejson

from django.db import models
from django.core import urlresolvers
from django.contrib.auth.models import User
from jobsub.parameterization import find_parameters, bind_parameters

from django.utils.translation import ugettext_lazy as _

LOG = logging.getLogger(__name__)


class JobDesign(models.Model):
  """
  DEPRECATED!!!
      This is the old Hue 1.x job design model. In Hue 2, the design is modeled
      after Oozie workflows.

  Contains CMS information for "job designs".
  """
  owner = models.ForeignKey(User)
  name = models.CharField(max_length=40)
  description = models.CharField(max_length=1024)
  last_modified = models.DateTimeField(auto_now=True)
  # Type corresponds to a JobSubForm that gets registered in jobsub.forms.interface.registry
  type = models.CharField(max_length=128)
  # Data is serialized via JobSubFormInterface.serialize_[to|from]_string
  data = models.TextField()

  def edit_url(self):
    return urlresolvers.reverse("jobsub.views.edit_design", kwargs=dict(id=self.id))

  def clone_url(self):
    return urlresolvers.reverse("jobsub.views.clone_design", kwargs=dict(id=self.id))

  def delete_url(self):
    return urlresolvers.reverse("jobsub.views.delete_design", kwargs=dict(id=self.id))

  def submit_url(self):
    return urlresolvers.reverse("jobsub.views.submit_design", kwargs=dict(id=self.id))

  def clone(self):
    clone_kwargs = dict([(field.name, getattr(self, field.name)) for field in self._meta.fields if field.name != 'id']);
    return self.__class__.objects.create(**clone_kwargs)

  def to_jsonable(self):
    return {
      'owner': self.owner.username,
      'name': self.name,
      'last_modified': str(self.last_modified),
      'type': self.type,
      'data': repr(self.data)
    }

class CheckForSetup(models.Model):
  """
  A model which should have at most one row, indicating
  whether jobsub_setup has run succesfully.
  """
  # Pre-Hue2 setup
  setup_run = models.BooleanField()
  # What kind of setup have we done?
  setup_level = models.IntegerField(default=0)


################################## New Models ################################

PATH_MAX = 512


class OozieAction(models.Model):
  """
  DEPRECATED!!!
      This is the old Hue 2.0/2.1 job design model. In Hue 2.2 and newer,
      Oozie models are used.

  The OozieAction model is an abstract base class. All concrete actions
  derive from it. And it provides something for the OozieDesign to
  reference. See
  https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance
  """
  PARAM_FIELDS = ( )    # Nothing is parameterized by default

  # This allows the code to easily figure out which subclass to access
  action_type = models.CharField(max_length=64, blank=False)

  def find_parameters(self):
    """Return a list of parameters in the various fields"""
    return find_parameters(self, self.PARAM_FIELDS)

  def bind_parameters(self, mapping):
    """
    Change the values of the model object by replacing the param variables
    with actual values.

    Mapping is a dictionary of variable to value.
    """
    # We're going to alter this object. Disallow saving (for models).
    self.save = None
    bind_parameters(self, mapping, self.PARAM_FIELDS)


class OozieDesign(models.Model):
  """
  DEPRECATED!!!
      This is the old Hue 2.0/2.1 job design model. In Hue 2.2 and newer,
      Oozie models are used.

  Contains information about all (Oozie) designs. Specific action info are
  stored in the Oozie*Action models.
  """
  # Generic stuff
  owner = models.ForeignKey(User)
  name = models.CharField(max_length=64, blank=False,
      help_text=_('Name of the design, which must be unique per user.'))
  description = models.CharField(max_length=1024, blank=True)
  last_modified = models.DateTimeField(auto_now=True)

  # Action. Avoid using `root_action' directly, because it only gives you the
  # intermediate table (i.e. OozieAction). You want to use `get_root_action()'
  # most of the time.
  root_action = models.ForeignKey(OozieAction)

  def get_root_action(self):
    """Return the concrete action object, not just a generic OozieAction"""
    root = self.root_action
    if root is None:
      return None