from datetime import datetime
from app import db
from app.utils import misc

class ReviewForm(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    application_form_id = db.Column(db.Integer(), db.ForeignKey('application_form.id'), nullable=False)
    is_open = db.Column(db.Boolean(), nullable=False)
    deadline = db.Column(db.DateTime(), nullable=False)

    application_form = db.relationship('ApplicationForm', foreign_keys=[application_form_id])
    review_questions = db.relationship('ReviewQuestion')

    def __init__(self, application_form_id, deadline):
        self.application_form_id = application_form_id
        self.is_open = True
        self.deadline = deadline

    def close(self):
        self.is_open = False


class ReviewQuestion(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    review_form_id = db.Column(db.Integer(), db.ForeignKey('review_form.id'), nullable=False)
    question_id = db.Column(db.Integer(), db.ForeignKey('question.id'), nullable=True)
    
    type = db.Column(db.String(), nullable=False)
    
    is_required = db.Column(db.Boolean(), nullable=False)
    order = db.Column(db.Integer(), nullable=False)
    weight = db.Column(db.Float(), nullable=False)
    review_form = db.relationship('ReviewForm', foreign_keys=[review_form_id])
    question = db.relationship('Question', foreign_keys=[question_id])

    translations = db.relationship('ReviewQuestionTranslation', lazy='dynamic')

    def __init__(self,
                 review_form_id,
                 question_id,
                 type,
                 is_required,
                 order,
                 weight):
        self.review_form_id = review_form_id
        self.question_id = question_id
        self.type = type
        self.is_required = is_required
        self.order = order
        self.weight = weight

    def get_translation(self, language):
        translation = self.translations.filter_by(language=language).first()
        return translation


class ReviewQuestionTranslation(db.Model):
    __tablename__ = 'review_question_translation'
    __table_args__ = tuple([db.UniqueConstraint('review_question_id', 'language', name='uq_review_question_id_language')])

    id = db.Column(db.Integer(), primary_key=True)
    review_question_id = db.Column(db.Integer(), db.ForeignKey('review_question.id'), nullable=False)
    language = db.Column(db.String(2), nullable=False)

    description = db.Column(db.String(), nullable=True)
    headline = db.Column(db.String(), nullable=True)
    placeholder = db.Column(db.String(), nullable=True)
    options = db.Column(db.JSON(), nullable=True)
    validation_regex = db.Column(db.String(), nullable=True)
    validation_text = db.Column(db.String(), nullable=True)

    def __init__(self, 
                 review_question_id,
                 language, 
                 description=None, 
                 headline=None, 
                 placeholder=None, 
                 options=None, 
                 validation_regex=None, 
                 validation_text=None):
        self.review_question_id = review_question_id
        self.language = language
        self.description = description
        self.headline = headline
        self.placeholder = placeholder
        self.options = options
        self.validation_regex = validation_regex
        self.validation_text = validation_text


class ReviewResponse(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    review_form_id = db.Column(db.Integer(), db.ForeignKey('review_form.id'), nullable=False)
    reviewer_user_id = db.Column(db.Integer(), db.ForeignKey('app_user.id'), nullable=False)
    response_id = db.Column(db.Integer(), db.ForeignKey('response.id'), nullable=False)
    submitted_timestamp = db.Column(db.DateTime(), nullable=False)
    language = db.Column(db.String(2), nullable=False)
    is_submitted = db.Column(db.Boolean(), nullable=False)
    submitted_timestamp = db.Column(db.DateTime(), nullable=True)

    review_form = db.relationship('ReviewForm', foreign_keys=[review_form_id])
    reviewer_user = db.relationship('AppUser', foreign_keys=[reviewer_user_id])
    response = db.relationship('Response', foreign_keys=[response_id])
    review_scores = db.relationship('ReviewScore')

    def __init__(self,
                 review_form_id,
                 reviewer_user_id,
                 response_id,
                 language):
        self.review_form_id = review_form_id
        self.reviewer_user_id = reviewer_user_id
        self.response_id = response_id
        self.language = language
        self.is_submitted = False

    def submit(self):
        self.is_submitted = True
        self.submitted_timestamp = datetime.now()

    def calculate_score(self):
        return sum([
            misc.try_parse_float(score.value) * score.review_question.weight for score in self.review_scores
            if score.review_question.weight > 0
        ])


class ReviewScore(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    review_response_id = db.Column(db.Integer(), db.ForeignKey('review_response.id'), nullable=False)
    review_question_id = db.Column(db.Integer(), db.ForeignKey('review_question.id'), nullable=False)
    value = db.Column(db.String(), nullable=False)

    review_response = db.relationship('ReviewResponse', foreign_keys=[review_response_id])
    review_question = db.relationship('ReviewQuestion', foreign_keys=[review_question_id])

    def __init__(self,
                 review_question_id,
                 value):
        self.review_question_id = review_question_id
        self.value = value


class ReviewConfiguration(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    review_form_id = db.Column(db.Integer(), db.ForeignKey('review_form.id'), nullable=False)
    num_reviews_required = db.Column(db.Integer(), nullable=False)
    num_optional_reviews = db.Column(db.Integer(), nullable=False)
    drop_optional_question_id = db.Column(db.Integer(), db.ForeignKey('review_question.id'), nullable=True)
    drop_optional_agreement_values = db.Column(db.String(), nullable=True)

    review_form = db.relationship('ReviewForm', foreign_keys=[review_form_id])
    review_question = db.relationship('ReviewQuestion', foreign_keys=[drop_optional_question_id])

[((404, 474), 'app.db.relationship', 'db.relationship', (['"""ApplicationForm"""'], {'foreign_keys': '[application_form_id]'}), "('ApplicationForm', foreign_keys=[application_form_id])\n", (419, 474), False, 'from app import db\n'), ((499, 532), 'app.db.relationship', 'db.relationship', (['"""ReviewQuestion"""'], {}), "('ReviewQuestion')\n", (514, 532), False, 'from app import db\n'), ((811, 850), 'app.db.Column', 'db.Column', (['db.Integer'], {'primary_key': '(True)'}), '(db.Integer, primary_key=True)\n', (820, 850), False, 'from app import db\n'), ((1280, 1340), 'app.db.relationship', 'db.relationship', (['"""ReviewForm"""'], {'foreign_keys': '[review_form_id]'}), "('ReviewForm', foreign_keys=[review_form_id])\n", (1295, 1340), False, 'from app import db\n'), ((1357, 1412), 'app.db.relationship', 'db.relationship', (['"""Question"""'], {'foreign_keys': '[question_id]'}), "('Question', foreign_keys=[question_id])\n", (1372, 1412), False, 'from app import db\n'), ((1435, 1495), 'app.db.relationship', 'db.relationship', (['"""ReviewQuestionTranslation"""'], {'lazy': '"""dynamic"""'}), "('ReviewQuestionTranslation', lazy='dynamic')\n", (1450, 1495), False, 'from app import db\n'), ((4123, 4183), 'app.db.relationship', 'db.relationship', (['"""ReviewForm"""'], {'foreign_keys': '[review_form_id]'}), "('ReviewForm', foreign_keys=[review_form_id])\n", (4138, 4183), False, 'from app import db\n'), ((4205, 4264), 'app.db.relationship', 'db.relationship', (['"""AppUser"""'], {'foreign_keys': '[reviewer_user_id]'}), "('AppUser', foreign_keys=[reviewer_user_id])\n", (4220, 4264), False, 'from app import db\n'), ((4281, 4336), 'app.db.relationship', 'db.relationship', (['"""Response"""'], {'foreign_keys': '[response_id]'}), "('Response', foreign_keys=[response_id])\n", (4296, 4336), False, 'from app import db\n'), ((4358, 4388), 'app.db.relationship', 'db.relationship', (['"""ReviewScore"""'], {}), "('ReviewScore')\n", (4373, 4388), False, 'from app import db\n'), ((5456, 5524), 'app.db.relationship', 'db.relationship', (['"""ReviewResponse"""'], {'foreign_keys': '[review_response_id]'}), "('ReviewResponse', foreign_keys=[review_response_id])\n", (5471, 5524), False, 'from app import db\n'), ((5548, 5616), 'app.db.relationship', 'db.relationship', (['"""ReviewQuestion"""'], {'foreign_keys': '[review_question_id]'}), "('ReviewQuestion', foreign_keys=[review_question_id])\n", (5563, 5616), False, 'from app import db\n'), ((6320, 6380), 'app.db.relationship', 'db.relationship', (['"""ReviewForm"""'], {'foreign_keys': '[review_form_id]'}), "('ReviewForm', foreign_keys=[review_form_id])\n", (6335, 6380), False, 'from app import db\n'), ((6404, 6479), 'app.db.relationship', 'db.relationship', (['"""ReviewQuestion"""'], {'foreign_keys': '[drop_optional_question_id]'}), "('ReviewQuestion', foreign_keys=[drop_optional_question_id])\n", (6419, 6479), False, 'from app import db\n'), ((129, 141), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (139, 141), False, 'from app import db\n'), ((198, 210), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (208, 210), False, 'from app import db\n'), ((212, 248), 'app.db.ForeignKey', 'db.ForeignKey', (['"""application_form.id"""'], {}), "('application_form.id')\n", (225, 248), False, 'from app import db\n'), ((291, 303), 'app.db.Boolean', 'db.Boolean', ([], {}), '()\n', (301, 303), False, 'from app import db\n'), ((347, 360), 'app.db.DateTime', 'db.DateTime', ([], {}), '()\n', (358, 360), False, 'from app import db\n'), ((883, 895), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (893, 895), False, 'from app import db\n'), ((897, 928), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_form.id"""'], {}), "('review_form.id')\n", (910, 928), False, 'from app import db\n'), ((975, 987), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (985, 987), False, 'from app import db\n'), ((989, 1017), 'app.db.ForeignKey', 'db.ForeignKey', (['"""question.id"""'], {}), "('question.id')\n", (1002, 1017), False, 'from app import db\n'), ((1062, 1073), 'app.db.String', 'db.String', ([], {}), '()\n', (1071, 1073), False, 'from app import db\n'), ((1126, 1138), 'app.db.Boolean', 'db.Boolean', ([], {}), '()\n', (1136, 1138), False, 'from app import db\n'), ((1179, 1191), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (1189, 1191), False, 'from app import db\n'), ((1233, 1243), 'app.db.Float', 'db.Float', ([], {}), '()\n', (1241, 1243), False, 'from app import db\n'), ((2299, 2311), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (2309, 2311), False, 'from app import db\n'), ((2367, 2379), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (2377, 2379), False, 'from app import db\n'), ((2381, 2416), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_question.id"""'], {}), "('review_question.id')\n", (2394, 2416), False, 'from app import db\n'), ((2460, 2472), 'app.db.String', 'db.String', (['(2)'], {}), '(2)\n', (2469, 2472), False, 'from app import db\n'), ((2521, 2532), 'app.db.String', 'db.String', ([], {}), '()\n', (2530, 2532), False, 'from app import db\n'), ((2575, 2586), 'app.db.String', 'db.String', ([], {}), '()\n', (2584, 2586), False, 'from app import db\n'), ((2632, 2643), 'app.db.String', 'db.String', ([], {}), '()\n', (2641, 2643), False, 'from app import db\n'), ((2685, 2694), 'app.db.JSON', 'db.JSON', ([], {}), '()\n', (2692, 2694), False, 'from app import db\n'), ((2745, 2756), 'app.db.String', 'db.String', ([], {}), '()\n', (2754, 2756), False, 'from app import db\n'), ((2806, 2817), 'app.db.String', 'db.String', ([], {}), '()\n', (2815, 2817), False, 'from app import db\n'), ((3541, 3553), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (3551, 3553), False, 'from app import db\n'), ((3605, 3617), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (3615, 3617), False, 'from app import db\n'), ((3619, 3650), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_form.id"""'], {}), "('review_form.id')\n", (3632, 3650), False, 'from app import db\n'), ((3702, 3714), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (3712, 3714), False, 'from app import db\n'), ((3716, 3744), 'app.db.ForeignKey', 'db.ForeignKey', (['"""app_user.id"""'], {}), "('app_user.id')\n", (3729, 3744), False, 'from app import db\n'), ((3791, 3803), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (3801, 3803), False, 'from app import db\n'), ((3805, 3833), 'app.db.ForeignKey', 'db.ForeignKey', (['"""response.id"""'], {}), "('response.id')\n", (3818, 3833), False, 'from app import db\n'), ((3888, 3901), 'app.db.DateTime', 'db.DateTime', ([], {}), '()\n', (3899, 3901), False, 'from app import db\n'), ((3945, 3957), 'app.db.String', 'db.String', (['(2)'], {}), '(2)\n', (3954, 3957), False, 'from app import db\n'), ((4005, 4017), 'app.db.Boolean', 'db.Boolean', ([], {}), '()\n', (4015, 4017), False, 'from app import db\n'), ((4072, 4085), 'app.db.DateTime', 'db.DateTime', ([], {}), '()\n', (4083, 4085), False, 'from app import db\n'), ((4845, 4859), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (4857, 4859), False, 'from datetime import datetime\n'), ((5141, 5153), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (5151, 5153), False, 'from app import db\n'), ((5209, 5221), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (5219, 5221), False, 'from app import db\n'), ((5223, 5258), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_response.id"""'], {}), "('review_response.id')\n", (5236, 5258), False, 'from app import db\n'), ((5312, 5324), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (5322, 5324), False, 'from app import db\n'), ((5326, 5361), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_question.id"""'], {}), "('review_question.id')\n", (5339, 5361), False, 'from app import db\n'), ((5402, 5413), 'app.db.String', 'db.String', ([], {}), '()\n', (5411, 5413), False, 'from app import db\n'), ((5851, 5863), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (5861, 5863), False, 'from app import db\n'), ((5915, 5927), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (5925, 5927), False, 'from app import db\n'), ((5929, 5960), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_form.id"""'], {}), "('review_form.id')\n", (5942, 5960), False, 'from app import db\n'), ((6016, 6028), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (6026, 6028), False, 'from app import db\n'), ((6084, 6096), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (6094, 6096), False, 'from app import db\n'), ((6157, 6169), 'app.db.Integer', 'db.Integer', ([], {}), '()\n', (6167, 6169), False, 'from app import db\n'), ((6171, 6206), 'app.db.ForeignKey', 'db.ForeignKey', (['"""review_question.id"""'], {}), "('review_question.id')\n", (6184, 6206), False, 'from app import db\n'), ((6271, 6282), 'app.db.String', 'db.String', ([], {}), '()\n', (6280, 6282), False, 'from app import db\n'), ((2182, 2279), 'app.db.UniqueConstraint', 'db.UniqueConstraint', (['"""review_question_id"""', '"""language"""'], {'name': '"""uq_review_question_id_language"""'}), "('review_question_id', 'language', name=\n    'uq_review_question_id_language')\n", (2201, 2279), False, 'from app import db\n'), ((4929, 4962), 'app.utils.misc.try_parse_float', 'misc.try_parse_float', (['score.value'], {}), '(score.value)\n', (4949, 4962), False, 'from app.utils import misc\n')]