# -*- coding: utf-8 -*-
"""
    hecuba.models
    ~~~~~~~~~~~~~

    Models classes for ORM

    :copyright: (c) 2016 by Hugo Cisneiros.
    :license: GPLv2, see LICENSE for more details.
"""
from hecuba import db
from flask_restful import fields
import datetime
import time

def dump_datetime(value, format="ISO"):
    """
    Deserialize datetime object into string form for JSON processing.

    Args:
        value (DateTime): Python DateTime object for converting into a human
            readable format string.
        format (Optional|str): Format for the ouput. Defaults to ISO 8601
            YYYY-mm-dd HH:MM:SS.SSSSS. Can also be "UnixTimestamp" for,
            obviously, return a unix timestamp.

    Returns:
        str: the converted date time string
    """
    if value is None:
        return None

    if (format == "UnixTimestamp"):
        return time.mktime(value.timetuple())

    return value.strftime("%Y-%m-%d %H:%M:%S")

cluster_fields = {
    'name': fields.String,
    'running': fields.Boolean,
    'last_updated': fields.String,
    'last_updated_timestamp': fields.Integer,
    'uri': fields.Url('cluster')
}

class Cluster(db.Model):
    """
    Represents a named cluster

    Attributes:
        name (str): The name of the cluster
        running (bool): True if cluster is running a task, False if it isn't.
        last_updated (DateTime): Last time any of the cluster attributes were
            updated.
        secret (str): The password for managing/updating the cluster, hashed
        nodes (models.Node): Backreference to a nodes model with the nodes
            that belongs to the cluster
    """
    name = db.Column(db.String(50), primary_key=True)
    running = db.Column(db.Boolean, default=False)
    last_updated = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    secret = db.Column(db.String(64), default=None)
    nodes = db.relationship('Node', backref='node', lazy='dynamic')

    def __init__(self, name, secret):
        self.name = name
        self.secret = secret

    def __repr__(self):
        """
        Gives a text representation of the Cluster object

        Returns:
            str: the text representation of the cluster object reference
        """
        return "<Cluster %r>" % self.name

    @property
    def serialize(self):
        """
        Return object data in easily serializable format

        Returns:
            dict: the class public attributes
        
        """
        return {
            'name': self.name,
            'running': self.running,
            'last_updated': dump_datetime(self.last_updated),
            'last_updated_timestamp': dump_datetime(self.last_updated, "UnixTimestamp")
        }

node_fields = {
    'name': fields.String,
    'running': fields.Boolean,
    'last_updated': fields.String,
    'last_updated_timestamp': fields.Integer,
    'error': fields.Boolean,
    'cluster_name': fields.String,
    'uri': fields.Url('node')
}

class Node(db.Model):
    """
    Represents a named node

    Attributes:
        name (str): The name of the node (usually the hostname)
        running (bool): True if the node is running a task, False if it isn't.
        last_updated (DateTime): Last time any of the node attributes were
            updated.
        error (bool): True if the last task went wrong, False if it weren't.
        cluster_name (str): the name of the cluster that the node belongs
    """
    name = db.Column(db.String(255), primary_key=True)
    running = db.Column(db.Boolean, default=False)
    last_updated = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    error = db.Column(db.Boolean, default=False)
    cluster_name = db.Column(db.String(255), db.ForeignKey('cluster.name'))

    def __init__(self, name, cluster_name):
        self.name = name
        self.cluster_name = cluster_name
        
    def __repr__(self):
        """
        Gives a text representation of the Node object

        Returns:
            str: the text representation of the node object reference
        """
        return "<Node %r>" % self.name

    @property
    def serialize(self):
        """
        Return object data in easily serializable format

        Returns:
            dict: the class public attributes
        
        """
        return {
            'name': self.name,
            'running': self.running,
            'last_updated': dump_datetime(self.last_updated),
            'last_updated_timestamp': dump_datetime(self.last_updated, "UnixTimestamp"),
            'error': self.error,
            'cluster_name': self.cluster_name
        }
