<commit_before># -*- coding: utf-8 -*-
import os
import uuid
import subprocess
import datetime
import time
import random

from django.db import models, IntegrityError
from django.utils.text import slugify
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, EmailMessage
from django.contrib.auth.models import User
from django.template.loader import render_to_string
from django.conf import settings

from geopy import geocoders
from .utils import print_pdf

# import reversion
here = lambda x: os.path.join(os.path.dirname(os.path.abspath(__file__)), x)


class Continent(models.Model):
    name = models.CharField(max_length=192, unique=True, blank=True)

    def __unicode__(self):
        return self.name


class Country(models.Model):
    name = models.CharField(max_length=192, unique=True, blank=True)
    iso_code = models.CharField(max_length=6, unique=True, blank=True)
    developing = models.BooleanField()
    continent = models.ForeignKey(Continent, null=True, blank=True)

    class Meta:
        ordering = ('name',)

    def __unicode__(self):
        return self.name


ORGANIZATION_MEMBERSHIP_TYPE_CHOICES = (
    (5, 'Institutional Members'),
    (10, 'Institutional Members - MRC'),
    (11, 'Institutional Members - DC'),
    (12, 'Institutional Members - DC - MRC'),

    (9, 'Associate Institutional Members'),
    (17, 'Associate Institutional Members - DC'),

    (6, 'Organizational Members'),
    (13, 'Organizational Members - DC'),
    (18, 'Organizational Members - MRC'),

    (7, 'Associate Consortium Members'),
    (14, 'Associate Consortium Members - DC'),

    (8, 'Corporate Members - Basic'),
    (15, 'Corporate Members - Premium'),
    (16, 'Corporate Members - Sustaining'),

)

ORGANIZATION_TYPE_CHOICES = (
    ('university', 'Higher Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('regionalconsortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity')
)

INSTITUTION_TYPE_CHOICES = (
    ('higher-ed', 'Higher Education Institution'),
    ('secondary-ed', 'Secondary Education Institution'),
    ('primary-ed', 'Primary Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('igo', 'Intergovernmental Organization (IGO)'),
    ('gov', 'Governmental Entity'),
    ('consortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity'),
)

ORGANIZATION_MEMBERSHIP_STATUS = (
    (1, 'Applied'),
    (2, 'Current'),
    (3, 'Grace'),
    (4, 'Expired'),
    (5, 'Pending'),
    (6, 'Cancelled'),
    (7, 'Sustaining'),
    # (8,   'Deceased'),
    # (9,   'Testing'),
    # (10,'Committee'),
    # (11,'Committee'),
    # (12,'Suspended'),
    # (13,'New'),
    (99, 'Example')
)

ORGANIZATION_ASSOCIATED_CONSORTIUM = (
    ('CCCOER', 'Community College Consortium for Open Educational Resources (CCCOER)'),
    ('CORE', 'CORE'),
    ('JOCWC', 'Japan OCW Consortium'),
    ('KOCWC', 'Korea OCW Consortium'),
    ('TOCWC', 'Taiwan OCW Consortium'),
    ('Turkish OCWC', 'Turkish OpenCourseWare Consortium'),
    ('UNIVERSIA', 'UNIVERSIA'),
    ('FOCW', 'OCW France'),
    ('OTHER', 'OTHER')
)


class ActiveOrganizationManager(models.Manager):
    def get_queryset(self):
        return super(ActiveOrganizationManager, self).get_queryset().filter(
            membership_status__in=(2, 3, 5, 7, 99)).order_by('display_name')


class Organization(models.Model):
    legal_name = models.CharField(max_length=255, blank=True)
    display_name = models.CharField(max_length=255, verbose_name="Name of the organization")
    slug = models.CharField(max_length=60, unique=True, default='')
    user = models.ForeignKey(User, blank=True, null=True)

    membership_type = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_TYPE_CHOICES)
    # organization_type = models.CharField(max_length=255, choices=ORGANIZATION_TYPE_CHOICES)
    membership_status = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_STATUS)
    associate_consortium = models.CharField(max_length=255, choices=ORGANIZATION_ASSOCIATED_CONSORTIUM, blank=True,
                                            default='')

    crmid = models.CharField(max_length=255, blank=True, help_text='Legacy identifier')

    main_website = models.TextField(max_length=255, blank=True)
    ocw_website = models.TextField(max_length=255, blank=True, verbose_name="OCW Website")

    description = models.TextField(blank=True)
    logo_large = models.ImageField(max_length=255, upload_to="logos", blank=True)
    logo_small = models.ImageField(max_length=255, upload_to="logos", blank=True)
    rss_course_feed = models.CharField(max_length=255, blank=True)

    accreditation_body = models.CharField(max_length=255, blank=True, default='')
    support_commitment = models.TextField(blank=True, default='')

    ocw_contact = models.ForeignKey(User, null=True, verbose_name=u'Primary contact inside OCW',
                                    related_name='ocw_contact_user',
                                    limit_choices_to={'is_staff': True})

    created = models.DateTimeField(blank=True, null=True, auto_now_add=True)

    institution_type = models.CharField(max_length=25, blank=True, choices=INSTITUTION_TYPE_CHOICES, default='')
    initiative_description1 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url1 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description2 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url2 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description3 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url3 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    objects = models.Manager()
    active = ActiveOrganizationManager()

    def __unicode__(self):
        return self.display_name

    def get_absolute_staff_url(self):
        return reverse('staff:organization-view', kwargs={'pk': self.id})

    def get_absolute_url(self):
        return reverse('crm:organization-view', kwargs={'pk': self.id})

    def get_logo_small_url(self):
        return 'http://www.oeconsortium.org/media/%s' % self.logo_small

    def save(self, force_insert=False, force_update=False, using=None):
        if not self.slug:
            slug = slugify(self.display_name)[:30]
            if Organization.objects.filter(slug=slug).exists():
                slug = slug[:29] + '2'
            self.slug = slug

        super(Organization, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_membership_due_amount(self):
        # Sustaining members
        if self.membership_status in [7]:
            return 0  # manually processed

        # (8 , 'Corporate Members - Basic'),
        if self.membership_type in [8]:
            return 1000

        # (5 , 'Institutional Members'),
        # (6 , 'Organizational Members'),
        # (11, 'Institutional Members - DC'),
        # (7 , 'Associate Consortium Members'),
        # (13, 'Organizational Members - DC'),
        if self.membership_type in [5, 6, 11, 7, 13]:
            if self.address_set.latest('id').country.developing:
                return 375
            else:
                return 750

        # (10, 'Institutional Members - MRC'),
        # (12, 'Institutional Members - DC - MRC'),
        # (9 , 'Associate Institutional Members'),
        # (17, 'Associate Institutional Members - DC')
        # (14, 'Associate Consortium Members - DC'),
        # (18, 'Organizational Members - MRC'),
        if self.membership_type in [10, 12, 9, 17, 14]:
            if self.address_set.latest('id').country.developing:
                return 225
            else:
                return 525

    def get_invoice_status(self):
        return {
            'create_invoice': self.billinglog_set.filter(log_type='create_invoice',
                                                         invoice_year=settings.DEFAULT_INVOICE_YEAR).exists(),
            'send_invoice': self.billinglog_set.filter(log_type='send_invoice',
                                                       invoice_year=settings.DEFAULT_INVOICE_YEAR).exists(),
        }

    def get_last_year_invoice_status(self):
        return {
            'create_invoice': self.billinglog_set.filter(log_type='create_invoice',
                                                         invoice_year=settings.PREVIOUS_INVOICE_YEAR).exists(),
            'send_invoice': self.billinglog_set.filter(log_type='send_invoice',
                                                       invoice_year=settings.PREVIOUS_INVOICE_YEAR).exists(),
        }

    def get_consortia_members(self):

        consortia = None
        if self.slug == 'cccoer':
            consortia = 'CCCOER'
        elif self.slug == 'japan-ocw-consortium':
            consortia = 'JOCWC'
        elif self.slug == 'korea-ocw-consortium':
            consortia = 'KOCWC'
        elif self.slug == 'taiwan-ocw-consortium':
            consortia = 'TOCWC'
        elif self.slug == 'turkish-ocw-consortium':
            consortia = 'Turkish OCWC'
        elif self.slug == 'taiwan-ocw-consortium':
            consortia = 'TOCWC'
        elif self.slug == 'universia':
            consortia = 'UNIVERSIA'
        elif self.slug == 'ocwfrance':
            consortia = 'FOCW'

        if not consortia:
            return Organization.objects.none()

        return Organization.objects.filter(associate_consortium=consortia)

    def can_vote(self):
        if self.membership_status in (2, 5, 7):  # exclude grace (3) from voting
            return True
        else:
            return False

    def get_number_of_votes(self):
        # if len(self.get_consortia_members()) > 30:
        #     return 5
        # elif len(self.get_consortia_members()) > 20:
        #     return 4
        # elif len(self.get_consortia_members()) > 10:
        #     return 3
        # elif len(self.get_consortia_members()) > 1:
        #     return 2

        return 1

    def get_bouncing_contacts(self):
        return self.contact_set.filter(bouncing=True)

    def get_simplified_membership(self):
        text = self.get_membership_type_display()
        text = text.replace('- MRC', '').replace('- DC', '').strip()
        return text

    def get_billing_address(self):
        try:
            address = self.address_set.filter(address_type='billing')[0]
        except IndexError:
            address = self.address_set.filter(address_type='primary')[0]

        return address

    def get_geo(self):
        try:
            address = self.address_set.filter(address_type='primary')[0]
            return {'latitude': address.latitude, 'longitude': address.longitude}
        except IndexError:
            try:
                address = self.address_set.filter(address_type='billing')[0]
                return {'latitude': address.latitude, 'longitude': address.longitude}
            except IndexError:
                pass


# reversion.register(Organization)

# CONTACT_TYPE_CHOICES = (
#   ('lead', 'Main contact'),
#   ('tech', 'Technical contact'),
#   ('billing', 'Billing contact')
# )

CONTACT_TYPE_CHOICES = (
    (4, 'Employee of'),
    (6, 'Lead Contact for'),
    (9, 'Certifier for'),
    (10, 'Voting Representative'),
    (11, 'Affiliated with'),
    (12, 'AC Member of'),
)


class Contact(models.Model):
    organization = models.ForeignKey(Organization)

    contact_type = models.IntegerField(choices=CONTACT_TYPE_CHOICES)
    email = models.EmailField(max_length=255)

    first_name = models.CharField(max_length=255, blank=True, default='')
    last_name = models.CharField(max_length=255, blank=True, default='')
    job_title = models.CharField(max_length=255, blank=True, default='')

    bouncing = models.BooleanField(default=False)


# reversion.register(Contact)

ADDRESS_TYPE = (
    ('primary', 'Primary Address'),
    ('billing', 'Billing Address')
)


class Address(models.Model):
    organization = models.ForeignKey(Organization)
    address_type = models.CharField(max_length=25, choices=ADDRESS_TYPE, default='primary')

    street_address = models.CharField(max_length=255, blank=True, help_text='Street address with street number')
    supplemental_address_1 = models.CharField(max_length=255, blank=True)
    supplemental_address_2 = models.CharField(max_length=255, blank=True)

    city = models.CharField(max_length=255, blank=True)
    postal_code = models.CharField(max_length=50, blank=True)
    postal_code_suffix = models.CharField(max_length=255, blank=True)

    state_province = models.CharField(max_length=255, blank=True)
    state_province_abbr = models.CharField(max_length=255, blank=True)

    country = models.ForeignKey(Country, blank=True, null=True)

    latitude = models.FloatField(blank=True, null=True)
    longitude = models.FloatField(blank=True, null=True)

    def __unicode__(self):
        if self.country:
            return u"%s %s %s" % (self.country.name, self.city, self.street_address)
        else:
            return u"%s %s" % (self.city, self.street_address)

    def save(self, force_insert=False, force_update=False, using=None):
        if self.country:
            g = geocoders.GoogleV3()

            address_string = u"%s, %s, %s, %s %s %s, %s, %s" % (
                self.street_address, self.supplemental_address_1, self.supplemental_address_2,
                self.postal_code, self.postal_code_suffix, self.city,
                self.state_province, self.country.name.replace(', Republic of', ''))
            address_string = address_string.replace(', ,', ', ')
            try:
                place, (lat, lng) = g.geocode(address_string)

                if lat:
                    self.latitude = lat
                    self.longitude = lng
            except:
                pass

        super(Address, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_absolute_url(self):
        return self.organization.get_absolute_url()


# reversion.register(Address)

APPLICATION_MEMBERSHIP_TYPE = (

)

APPLICATION_STATUS_CHOICES = (
    ('Submitted', 'Submitted'),
    ('Committee', 'Sent to Committee'),
    ('Approved', 'Approved'),
    ('Rejected', 'Rejected'),
    ('Spam', 'Spam'),
    ('RequestedMoreInfo', 'Requested more information'),
)

ORGANIZATION_TYPE_CHOICES = (
    ('university', 'Higher Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('regionalconsortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity'),
)

SIMPLIFIED_MEMBERSHIP_TYPE_CHOICES = (
    ('institutional', 'Institutional Member'),
    ('associate', 'Associate Consortium Member'),
    ('organizational', 'Organizational Member'),
    ('corporate', 'Corporate Member')
)

CORPORATE_SUPPORT_CHOICES = (
    ('basic', 'Basic - $1,000 annual membership fee'),
    # ('premium', 'Premium - $5,000 annual membership fee'),
    ('sustaining', 'Sustaining - $30,000 contribution annual membership fee'),
    ('bronze', 'Bronze - $60,000 contribution annual membership fee'),
    ('silver', 'Silver - $100,000 contribution annual membership fee'),
    ('gold', 'Gold - $150,000 contribution annual membership fee'),
    ('platinum', 'Platinum - $250,000 contribution annual membership fee'),
)

IS_ACCREDITED_CHOICES = (
    (1, 'Yes'),
    (0, 'No'),
)


class MembershipApplication(models.Model):
    organization = models.ForeignKey(Organization, blank=True, null=True,
                                     help_text='Should be empty, unless application is approved')
    membership_type = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_TYPE_CHOICES, blank=True,
                                          null=True, default=None)

    display_name = models.CharField(max_length=255, blank=True, verbose_name="Institution Name")

    edit_link_key = models.CharField(max_length=255, blank=True)
    view_link_key = models.CharField(max_length=255, blank=True)

    description = models.TextField(blank=True,
                                   help_text="Please write between 1000 – 1500 characters. <br />This information will be publicly displayed on your OEC profile site.")

    legacy_application_id = models.IntegerField(blank=True, null=True)
    legacy_entity_id = models.IntegerField(blank=True, null=True)

    main_website = models.CharField(max_length=765, blank=True, verbose_name=u'Main Website address')
    ocw_website = models.CharField(max_length=765, blank=True,
                                   verbose_name=u'Open Educational Resources (OER) or OpenCourseWare (OCW) Website')

    logo_large = models.ImageField(max_length=765, blank=True, upload_to="logos",
                                   verbose_name=u"Logo of your institution (at least 500x500px PNG or a vector (PDF, EPS) file)")
    logo_small = models.CharField(max_length=765, blank=True)

    institution_country = models.ForeignKey(Country, blank=True, null=True)

    rss_course_feed = models.CharField(max_length=765, blank=True)
    rss_referral_link = models.CharField(max_length=765, blank=True)
    rss_course_feed_language = models.CharField(max_length=765, blank=True)

    agreed_to_terms = models.CharField(max_length=765, blank=True)
    agreed_criteria = models.CharField(max_length=765, blank=True)
    contract_version = models.CharField(max_length=765, blank=True)

    ocw_software_platform = models.CharField(max_length=765, blank=True)
    ocw_platform_details = models.TextField(blank=True)
    ocw_site_hosting = models.CharField(max_length=765, blank=True)
    ocw_site_approved = models.NullBooleanField(null=True, blank=True)
    ocw_published_languages = models.CharField(max_length=765, blank=True)
    ocw_license = models.CharField(max_length=765, blank=True)

    organization_type = models.CharField(max_length=765, blank=True, choices=ORGANIZATION_TYPE_CHOICES, default='')
    institution_type = models.CharField(max_length=25, blank=True, choices=INSTITUTION_TYPE_CHOICES, default='')

    is_accredited = models.NullBooleanField(default=None, choices=IS_ACCREDITED_CHOICES, blank=True)
    accreditation_body = models.CharField(max_length=765, blank=True, default='')
    ocw_launch_date = models.DateTimeField(null=True, blank=True)

    support_commitment = models.TextField(blank=True)

    app_status = models.CharField(choices=APPLICATION_STATUS_CHOICES, max_length=255, blank=True)
    created = models.DateTimeField(blank=True, null=True, auto_now_add=True)
    modified = models.DateTimeField(blank=True)  # , null=True, auto_now=True)

    # address
    street_address = models.CharField(max_length=255, blank=True, help_text='Street address with a street number')
    supplemental_address_1 = models.CharField(max_length=255, blank=True, verbose_name=u'Street Address 2')
    supplemental_address_2 = models.CharField(max_length=255, blank=True, verbose_name=u'Street Address 3')

    city = models.CharField(max_length=255, blank=True)
    postal_code = models.CharField(max_length=50, blank=True)

    state_province = models.CharField(max_length=255, blank=True, verbose_name=u'State/Province')
    country = models.ForeignKey(Country, blank=True, null=True, related_name='app_country')

    email = models.EmailField(max_length=255, blank=True)

    first_name = models.CharField(max_length=255, blank=True, default='')
    last_name = models.CharField(max_length=255, blank=True, default='')
    job_title = models.CharField(max_length=255, blank=True, default='')

    simplified_membership_type = models.CharField(max_length=255, blank=True,
                                                  choices=SIMPLIFIED_MEMBERSHIP_TYPE_CHOICES)
    corporate_support_levels = models.CharField(max_length=255, blank=True, choices=CORPORATE_SUPPORT_CHOICES)
    associate_consortium = models.CharField(max_length=255, choices=ORGANIZATION_ASSOCIATED_CONSORTIUM, blank=True,
                                            default='')

    moa_terms = models.NullBooleanField(null=True)
    terms_of_use = models.NullBooleanField(null=True)
    coppa = models.NullBooleanField(null=True)

    initiative_description1 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url1 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description2 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url2 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description3 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url3 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    def save(self, force_insert=False, force_update=False, using=None):
        if not self.legacy_application_id:
            if not self.edit_link_key:
                self.edit_link_key = uuid.uuid4().get_hex()

        if not self.view_link_key:
            self.view_link_key = uuid.uuid4().get_hex()

        if not self.modified:
            self.modified = datetime.datetime.now()
        if not self.created:
            self.created = datetime.datetime.now()

        if not self.app_status:
            self.app_status = 'Submitted'

        if self.app_status == 'Approved' and not self.organization:
            self.organization = self._create_member()

        if not self.pk:
            self._send_notification_email()

        super(MembershipApplication, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_absolute_url(self):
        # return reverse('crm:application-view', kwargs={'view_link_key':self.view_link_key})
        return '/application/view/%s/' % self.view_link_key

    def __unicode__(self):
        return "Application #%s" % self.id

    def _create_member(self):
        org, is_created = Organization.objects.get_or_create(
            display_name=self.display_name,
            membership_type=self.membership_type,
            defaults={
                'membership_status': 5,  # pending
                'associate_consortium': self.associate_consortium,
                'main_website': self.main_website,
                'ocw_website': self.ocw_website,
                'description': self.description,
                'support_commitment': self.support_commitment,
                'institution_type': self.institution_type,
                'initiative_description1': self.initiative_description1,
                'initiative_url1': self.initiative_url1,
                'initiative_description2': self.initiative_description2,
                'initiative_url2': self.initiative_url2,
                'initiative_description3': self.initiative_description3,
                'initiative_url3': self.initiative_url3,
            })

        contact, is_created = Contact.objects.get_or_create(
            organization=org,
            contact_type=6,  # Lead contact
            email=self.email,
            defaults={
                'first_name': self.first_name,
                'last_name': self.last_name
            })

        try:
            user, is_created = User.objects.get_or_create(
                username=org.slug,
                email=contact.email
            )
        except IntegrityError:
            user, is_created = User.objects.get_or_create(
                username="{}-{}".format(org.slug[:25], int(round(random.random() * 10, 0))),
                email=contact.email,
                last_login=datetime.datetime.now()
            )

        org.user = user
        org.save()

        address, is_created = Address.objects.get_or_create(
            organization=org,
            street_address=self.street_address,
            defaults={
                'supplemental_address_1': self.supplemental_address_1,
                'supplemental_address_2': self.supplemental_address_2,

                'city': self.city,<commit_msg>Force short usernames<commit_after># -*- coding: utf-8 -*-
import os
import uuid
import subprocess
import datetime
import time
import random

from django.db import models, IntegrityError
from django.utils.text import slugify
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, EmailMessage
from django.contrib.auth.models import User
from django.template.loader import render_to_string
from django.conf import settings

from geopy import geocoders
from .utils import print_pdf

# import reversion
here = lambda x: os.path.join(os.path.dirname(os.path.abspath(__file__)), x)


class Continent(models.Model):
    name = models.CharField(max_length=192, unique=True, blank=True)

    def __unicode__(self):
        return self.name


class Country(models.Model):
    name = models.CharField(max_length=192, unique=True, blank=True)
    iso_code = models.CharField(max_length=6, unique=True, blank=True)
    developing = models.BooleanField()
    continent = models.ForeignKey(Continent, null=True, blank=True)

    class Meta:
        ordering = ('name',)

    def __unicode__(self):
        return self.name


ORGANIZATION_MEMBERSHIP_TYPE_CHOICES = (
    (5, 'Institutional Members'),
    (10, 'Institutional Members - MRC'),
    (11, 'Institutional Members - DC'),
    (12, 'Institutional Members - DC - MRC'),

    (9, 'Associate Institutional Members'),
    (17, 'Associate Institutional Members - DC'),

    (6, 'Organizational Members'),
    (13, 'Organizational Members - DC'),
    (18, 'Organizational Members - MRC'),

    (7, 'Associate Consortium Members'),
    (14, 'Associate Consortium Members - DC'),

    (8, 'Corporate Members - Basic'),
    (15, 'Corporate Members - Premium'),
    (16, 'Corporate Members - Sustaining'),

)

ORGANIZATION_TYPE_CHOICES = (
    ('university', 'Higher Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('regionalconsortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity')
)

INSTITUTION_TYPE_CHOICES = (
    ('higher-ed', 'Higher Education Institution'),
    ('secondary-ed', 'Secondary Education Institution'),
    ('primary-ed', 'Primary Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('igo', 'Intergovernmental Organization (IGO)'),
    ('gov', 'Governmental Entity'),
    ('consortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity'),
)

ORGANIZATION_MEMBERSHIP_STATUS = (
    (1, 'Applied'),
    (2, 'Current'),
    (3, 'Grace'),
    (4, 'Expired'),
    (5, 'Pending'),
    (6, 'Cancelled'),
    (7, 'Sustaining'),
    # (8,   'Deceased'),
    # (9,   'Testing'),
    # (10,'Committee'),
    # (11,'Committee'),
    # (12,'Suspended'),
    # (13,'New'),
    (99, 'Example')
)

ORGANIZATION_ASSOCIATED_CONSORTIUM = (
    ('CCCOER', 'Community College Consortium for Open Educational Resources (CCCOER)'),
    ('CORE', 'CORE'),
    ('JOCWC', 'Japan OCW Consortium'),
    ('KOCWC', 'Korea OCW Consortium'),
    ('TOCWC', 'Taiwan OCW Consortium'),
    ('Turkish OCWC', 'Turkish OpenCourseWare Consortium'),
    ('UNIVERSIA', 'UNIVERSIA'),
    ('FOCW', 'OCW France'),
    ('OTHER', 'OTHER')
)


class ActiveOrganizationManager(models.Manager):
    def get_queryset(self):
        return super(ActiveOrganizationManager, self).get_queryset().filter(
            membership_status__in=(2, 3, 5, 7, 99)).order_by('display_name')


class Organization(models.Model):
    legal_name = models.CharField(max_length=255, blank=True)
    display_name = models.CharField(max_length=255, verbose_name="Name of the organization")
    slug = models.CharField(max_length=60, unique=True, default='')
    user = models.ForeignKey(User, blank=True, null=True)

    membership_type = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_TYPE_CHOICES)
    # organization_type = models.CharField(max_length=255, choices=ORGANIZATION_TYPE_CHOICES)
    membership_status = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_STATUS)
    associate_consortium = models.CharField(max_length=255, choices=ORGANIZATION_ASSOCIATED_CONSORTIUM, blank=True,
                                            default='')

    crmid = models.CharField(max_length=255, blank=True, help_text='Legacy identifier')

    main_website = models.TextField(max_length=255, blank=True)
    ocw_website = models.TextField(max_length=255, blank=True, verbose_name="OCW Website")

    description = models.TextField(blank=True)
    logo_large = models.ImageField(max_length=255, upload_to="logos", blank=True)
    logo_small = models.ImageField(max_length=255, upload_to="logos", blank=True)
    rss_course_feed = models.CharField(max_length=255, blank=True)

    accreditation_body = models.CharField(max_length=255, blank=True, default='')
    support_commitment = models.TextField(blank=True, default='')

    ocw_contact = models.ForeignKey(User, null=True, verbose_name=u'Primary contact inside OCW',
                                    related_name='ocw_contact_user',
                                    limit_choices_to={'is_staff': True})

    created = models.DateTimeField(blank=True, null=True, auto_now_add=True)

    institution_type = models.CharField(max_length=25, blank=True, choices=INSTITUTION_TYPE_CHOICES, default='')
    initiative_description1 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url1 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description2 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url2 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description3 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url3 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    objects = models.Manager()
    active = ActiveOrganizationManager()

    def __unicode__(self):
        return self.display_name

    def get_absolute_staff_url(self):
        return reverse('staff:organization-view', kwargs={'pk': self.id})

    def get_absolute_url(self):
        return reverse('crm:organization-view', kwargs={'pk': self.id})

    def get_logo_small_url(self):
        return 'http://www.oeconsortium.org/media/%s' % self.logo_small

    def save(self, force_insert=False, force_update=False, using=None):
        if not self.slug:
            slug = slugify(self.display_name)[:30]
            if Organization.objects.filter(slug=slug).exists():
                slug = slug[:29] + '2'
            self.slug = slug

        super(Organization, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_membership_due_amount(self):
        # Sustaining members
        if self.membership_status in [7]:
            return 0  # manually processed

        # (8 , 'Corporate Members - Basic'),
        if self.membership_type in [8]:
            return 1000

        # (5 , 'Institutional Members'),
        # (6 , 'Organizational Members'),
        # (11, 'Institutional Members - DC'),
        # (7 , 'Associate Consortium Members'),
        # (13, 'Organizational Members - DC'),
        if self.membership_type in [5, 6, 11, 7, 13]:
            if self.address_set.latest('id').country.developing:
                return 375
            else:
                return 750

        # (10, 'Institutional Members - MRC'),
        # (12, 'Institutional Members - DC - MRC'),
        # (9 , 'Associate Institutional Members'),
        # (17, 'Associate Institutional Members - DC')
        # (14, 'Associate Consortium Members - DC'),
        # (18, 'Organizational Members - MRC'),
        if self.membership_type in [10, 12, 9, 17, 14]:
            if self.address_set.latest('id').country.developing:
                return 225
            else:
                return 525

    def get_invoice_status(self):
        return {
            'create_invoice': self.billinglog_set.filter(log_type='create_invoice',
                                                         invoice_year=settings.DEFAULT_INVOICE_YEAR).exists(),
            'send_invoice': self.billinglog_set.filter(log_type='send_invoice',
                                                       invoice_year=settings.DEFAULT_INVOICE_YEAR).exists(),
        }

    def get_last_year_invoice_status(self):
        return {
            'create_invoice': self.billinglog_set.filter(log_type='create_invoice',
                                                         invoice_year=settings.PREVIOUS_INVOICE_YEAR).exists(),
            'send_invoice': self.billinglog_set.filter(log_type='send_invoice',
                                                       invoice_year=settings.PREVIOUS_INVOICE_YEAR).exists(),
        }

    def get_consortia_members(self):

        consortia = None
        if self.slug == 'cccoer':
            consortia = 'CCCOER'
        elif self.slug == 'japan-ocw-consortium':
            consortia = 'JOCWC'
        elif self.slug == 'korea-ocw-consortium':
            consortia = 'KOCWC'
        elif self.slug == 'taiwan-ocw-consortium':
            consortia = 'TOCWC'
        elif self.slug == 'turkish-ocw-consortium':
            consortia = 'Turkish OCWC'
        elif self.slug == 'taiwan-ocw-consortium':
            consortia = 'TOCWC'
        elif self.slug == 'universia':
            consortia = 'UNIVERSIA'
        elif self.slug == 'ocwfrance':
            consortia = 'FOCW'

        if not consortia:
            return Organization.objects.none()

        return Organization.objects.filter(associate_consortium=consortia)

    def can_vote(self):
        if self.membership_status in (2, 5, 7):  # exclude grace (3) from voting
            return True
        else:
            return False

    def get_number_of_votes(self):
        # if len(self.get_consortia_members()) > 30:
        #     return 5
        # elif len(self.get_consortia_members()) > 20:
        #     return 4
        # elif len(self.get_consortia_members()) > 10:
        #     return 3
        # elif len(self.get_consortia_members()) > 1:
        #     return 2

        return 1

    def get_bouncing_contacts(self):
        return self.contact_set.filter(bouncing=True)

    def get_simplified_membership(self):
        text = self.get_membership_type_display()
        text = text.replace('- MRC', '').replace('- DC', '').strip()
        return text

    def get_billing_address(self):
        try:
            address = self.address_set.filter(address_type='billing')[0]
        except IndexError:
            address = self.address_set.filter(address_type='primary')[0]

        return address

    def get_geo(self):
        try:
            address = self.address_set.filter(address_type='primary')[0]
            return {'latitude': address.latitude, 'longitude': address.longitude}
        except IndexError:
            try:
                address = self.address_set.filter(address_type='billing')[0]
                return {'latitude': address.latitude, 'longitude': address.longitude}
            except IndexError:
                pass


# reversion.register(Organization)

# CONTACT_TYPE_CHOICES = (
#   ('lead', 'Main contact'),
#   ('tech', 'Technical contact'),
#   ('billing', 'Billing contact')
# )

CONTACT_TYPE_CHOICES = (
    (4, 'Employee of'),
    (6, 'Lead Contact for'),
    (9, 'Certifier for'),
    (10, 'Voting Representative'),
    (11, 'Affiliated with'),
    (12, 'AC Member of'),
)


class Contact(models.Model):
    organization = models.ForeignKey(Organization)

    contact_type = models.IntegerField(choices=CONTACT_TYPE_CHOICES)
    email = models.EmailField(max_length=255)

    first_name = models.CharField(max_length=255, blank=True, default='')
    last_name = models.CharField(max_length=255, blank=True, default='')
    job_title = models.CharField(max_length=255, blank=True, default='')

    bouncing = models.BooleanField(default=False)


# reversion.register(Contact)

ADDRESS_TYPE = (
    ('primary', 'Primary Address'),
    ('billing', 'Billing Address')
)


class Address(models.Model):
    organization = models.ForeignKey(Organization)
    address_type = models.CharField(max_length=25, choices=ADDRESS_TYPE, default='primary')

    street_address = models.CharField(max_length=255, blank=True, help_text='Street address with street number')
    supplemental_address_1 = models.CharField(max_length=255, blank=True)
    supplemental_address_2 = models.CharField(max_length=255, blank=True)

    city = models.CharField(max_length=255, blank=True)
    postal_code = models.CharField(max_length=50, blank=True)
    postal_code_suffix = models.CharField(max_length=255, blank=True)

    state_province = models.CharField(max_length=255, blank=True)
    state_province_abbr = models.CharField(max_length=255, blank=True)

    country = models.ForeignKey(Country, blank=True, null=True)

    latitude = models.FloatField(blank=True, null=True)
    longitude = models.FloatField(blank=True, null=True)

    def __unicode__(self):
        if self.country:
            return u"%s %s %s" % (self.country.name, self.city, self.street_address)
        else:
            return u"%s %s" % (self.city, self.street_address)

    def save(self, force_insert=False, force_update=False, using=None):
        if self.country:
            g = geocoders.GoogleV3()

            address_string = u"%s, %s, %s, %s %s %s, %s, %s" % (
                self.street_address, self.supplemental_address_1, self.supplemental_address_2,
                self.postal_code, self.postal_code_suffix, self.city,
                self.state_province, self.country.name.replace(', Republic of', ''))
            address_string = address_string.replace(', ,', ', ')
            try:
                place, (lat, lng) = g.geocode(address_string)

                if lat:
                    self.latitude = lat
                    self.longitude = lng
            except:
                pass

        super(Address, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_absolute_url(self):
        return self.organization.get_absolute_url()


# reversion.register(Address)

APPLICATION_MEMBERSHIP_TYPE = (

)

APPLICATION_STATUS_CHOICES = (
    ('Submitted', 'Submitted'),
    ('Committee', 'Sent to Committee'),
    ('Approved', 'Approved'),
    ('Rejected', 'Rejected'),
    ('Spam', 'Spam'),
    ('RequestedMoreInfo', 'Requested more information'),
)

ORGANIZATION_TYPE_CHOICES = (
    ('university', 'Higher Education Institution'),
    ('npo', 'Non-Profit Organization'),
    ('ngo', 'Non-Governmental Organization'),
    ('regionalconsortium', 'Regional Consortium'),
    ('software', 'Software Development'),
    ('commercial', 'Commercial Entity'),
)

SIMPLIFIED_MEMBERSHIP_TYPE_CHOICES = (
    ('institutional', 'Institutional Member'),
    ('associate', 'Associate Consortium Member'),
    ('organizational', 'Organizational Member'),
    ('corporate', 'Corporate Member')
)

CORPORATE_SUPPORT_CHOICES = (
    ('basic', 'Basic - $1,000 annual membership fee'),
    # ('premium', 'Premium - $5,000 annual membership fee'),
    ('sustaining', 'Sustaining - $30,000 contribution annual membership fee'),
    ('bronze', 'Bronze - $60,000 contribution annual membership fee'),
    ('silver', 'Silver - $100,000 contribution annual membership fee'),
    ('gold', 'Gold - $150,000 contribution annual membership fee'),
    ('platinum', 'Platinum - $250,000 contribution annual membership fee'),
)

IS_ACCREDITED_CHOICES = (
    (1, 'Yes'),
    (0, 'No'),
)


class MembershipApplication(models.Model):
    organization = models.ForeignKey(Organization, blank=True, null=True,
                                     help_text='Should be empty, unless application is approved')
    membership_type = models.IntegerField(choices=ORGANIZATION_MEMBERSHIP_TYPE_CHOICES, blank=True,
                                          null=True, default=None)

    display_name = models.CharField(max_length=255, blank=True, verbose_name="Institution Name")

    edit_link_key = models.CharField(max_length=255, blank=True)
    view_link_key = models.CharField(max_length=255, blank=True)

    description = models.TextField(blank=True,
                                   help_text="Please write between 1000 – 1500 characters. <br />This information will be publicly displayed on your OEC profile site.")

    legacy_application_id = models.IntegerField(blank=True, null=True)
    legacy_entity_id = models.IntegerField(blank=True, null=True)

    main_website = models.CharField(max_length=765, blank=True, verbose_name=u'Main Website address')
    ocw_website = models.CharField(max_length=765, blank=True,
                                   verbose_name=u'Open Educational Resources (OER) or OpenCourseWare (OCW) Website')

    logo_large = models.ImageField(max_length=765, blank=True, upload_to="logos",
                                   verbose_name=u"Logo of your institution (at least 500x500px PNG or a vector (PDF, EPS) file)")
    logo_small = models.CharField(max_length=765, blank=True)

    institution_country = models.ForeignKey(Country, blank=True, null=True)

    rss_course_feed = models.CharField(max_length=765, blank=True)
    rss_referral_link = models.CharField(max_length=765, blank=True)
    rss_course_feed_language = models.CharField(max_length=765, blank=True)

    agreed_to_terms = models.CharField(max_length=765, blank=True)
    agreed_criteria = models.CharField(max_length=765, blank=True)
    contract_version = models.CharField(max_length=765, blank=True)

    ocw_software_platform = models.CharField(max_length=765, blank=True)
    ocw_platform_details = models.TextField(blank=True)
    ocw_site_hosting = models.CharField(max_length=765, blank=True)
    ocw_site_approved = models.NullBooleanField(null=True, blank=True)
    ocw_published_languages = models.CharField(max_length=765, blank=True)
    ocw_license = models.CharField(max_length=765, blank=True)

    organization_type = models.CharField(max_length=765, blank=True, choices=ORGANIZATION_TYPE_CHOICES, default='')
    institution_type = models.CharField(max_length=25, blank=True, choices=INSTITUTION_TYPE_CHOICES, default='')

    is_accredited = models.NullBooleanField(default=None, choices=IS_ACCREDITED_CHOICES, blank=True)
    accreditation_body = models.CharField(max_length=765, blank=True, default='')
    ocw_launch_date = models.DateTimeField(null=True, blank=True)

    support_commitment = models.TextField(blank=True)

    app_status = models.CharField(choices=APPLICATION_STATUS_CHOICES, max_length=255, blank=True)
    created = models.DateTimeField(blank=True, null=True, auto_now_add=True)
    modified = models.DateTimeField(blank=True)  # , null=True, auto_now=True)

    # address
    street_address = models.CharField(max_length=255, blank=True, help_text='Street address with a street number')
    supplemental_address_1 = models.CharField(max_length=255, blank=True, verbose_name=u'Street Address 2')
    supplemental_address_2 = models.CharField(max_length=255, blank=True, verbose_name=u'Street Address 3')

    city = models.CharField(max_length=255, blank=True)
    postal_code = models.CharField(max_length=50, blank=True)

    state_province = models.CharField(max_length=255, blank=True, verbose_name=u'State/Province')
    country = models.ForeignKey(Country, blank=True, null=True, related_name='app_country')

    email = models.EmailField(max_length=255, blank=True)

    first_name = models.CharField(max_length=255, blank=True, default='')
    last_name = models.CharField(max_length=255, blank=True, default='')
    job_title = models.CharField(max_length=255, blank=True, default='')

    simplified_membership_type = models.CharField(max_length=255, blank=True,
                                                  choices=SIMPLIFIED_MEMBERSHIP_TYPE_CHOICES)
    corporate_support_levels = models.CharField(max_length=255, blank=True, choices=CORPORATE_SUPPORT_CHOICES)
    associate_consortium = models.CharField(max_length=255, choices=ORGANIZATION_ASSOCIATED_CONSORTIUM, blank=True,
                                            default='')

    moa_terms = models.NullBooleanField(null=True)
    terms_of_use = models.NullBooleanField(null=True)
    coppa = models.NullBooleanField(null=True)

    initiative_description1 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url1 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description2 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url2 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    initiative_description3 = models.TextField(blank=True, default='',
                                               verbose_name='Description (100 – 350 characters)')
    initiative_url3 = models.URLField(max_length=255, blank=True, default='', verbose_name='URL')

    def save(self, force_insert=False, force_update=False, using=None):
        if not self.legacy_application_id:
            if not self.edit_link_key:
                self.edit_link_key = uuid.uuid4().get_hex()

        if not self.view_link_key:
            self.view_link_key = uuid.uuid4().get_hex()

        if not self.modified:
            self.modified = datetime.datetime.now()
        if not self.created:
            self.created = datetime.datetime.now()

        if not self.app_status:
            self.app_status = 'Submitted'

        if self.app_status == 'Approved' and not self.organization:
            self.organization = self._create_member()

        if not self.pk:
            self._send_notification_email()

        super(MembershipApplication, self).save(force_insert=force_insert, force_update=force_update, using=using)

    def get_absolute_url(self):
        # return reverse('crm:application-view', kwargs={'view_link_key':self.view_link_key})
        return '/application/view/%s/' % self.view_link_key

    def __unicode__(self):
        return "Application #%s" % self.id

    def _create_member(self):
        org, is_created = Organization.objects.get_or_create(
            display_name=self.display_name,
            membership_type=self.membership_type,
            defaults={
                'membership_status': 5,  # pending
                'associate_consortium': self.associate_consortium,
                'main_website': self.main_website,
                'ocw_website': self.ocw_website,
                'description': self.description,
                'support_commitment': self.support_commitment,
                'institution_type': self.institution_type,
                'initiative_description1': self.initiative_description1,
                'initiative_url1': self.initiative_url1,
                'initiative_description2': self.initiative_description2,
                'initiative_url2': self.initiative_url2,
                'initiative_description3': self.initiative_description3,
                'initiative_url3': self.initiative_url3,
            })

        contact, is_created = Contact.objects.get_or_create(
            organization=org,
            contact_type=6,  # Lead contact
            email=self.email,
            defaults={
                'first_name': self.first_name,
                'last_name': self.last_name
            })

        try:
            user, is_created = User.objects.get_or_create(
                username=org.slug[:29],
                email=contact.email
            )
        except IntegrityError:
            user, is_created = User.objects.get_or_create(
                username="{}-{}".format(org.slug[:20], int(round(random.random() * 10, 0))),
                email=contact.email,
                last_login=datetime.datetime.now()
            )

        org.user = user
        org.save()

        address, is_created = Address.objects.get_or_create(
            organization=org,
            street_address=self.street_address,
            defaults={
                'supplemental_address_1': self.supplemental_address_1,
                'supplemental_address_2': self.supplemental_address_2,

                'city': self.city,
{'fraction_non_alphanumeric': 0.11787624911678611, 'fraction_numerical': 0.019016856767941858, 'mean_word_length': 3.0480509928904143, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 74, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2843243', 'n_tokens_mistral': 15767, 'n_tokens_neox': 14528, 'n_words': 2823}