#-*- python -*-
import logging
from datetime import datetime

from ming import schema as S
from ming.orm import ThreadLocalORMSession, session

from pylons import c

from allura import model as M

from forgediscussion import model as DM

log = logging.getLogger(__name__)

def validate_import(json, username_mapping, default_username=None):
    warnings = []
    schema = make_schema(username_mapping, default_username, warnings)
    json = schema.validate(json)
    return warnings, json

def perform_import(json, username_mapping, default_username=None, create_users=False):
    if create_users: default_username=create_user

    # Validate the import, create missing users
    warnings, json = validate_import(json, username_mapping, default_username)
    for w in warnings:
        log.warning('Importing to %s/%s: %s',
                    c.project.shortname,
                    c.app.config.options.mount_point,
                    w)

    for name, forum in json.forums.iteritems():
        log.info('... %s has %d threads with %d total posts',
                 name, len(forum.threads), sum(len(t) for t in forum.threads.itervalues()))

    for name, forum in json.forums.iteritems():
        log.info('... creating %s/%s: %s',
                 c.project.shortname,
                 c.app.config.options.mount_point,
                 name)
        f = DM.Forum(
            app_config_id=c.app.config._id,
            name=forum['name'],
            shortname=forum['name'],
            description=forum['description'])
        for tid, posts in forum.threads.iteritems():
            rest, head = posts[:-1], posts[-1]
            t = DM.ForumThread.new(
                _id=tid,
                discussion_id=f._id,
                subject=head['subject'])
            for p in posts:
                p = create_post(f._id, t._id, p)
            t.first_post_id=p._id
            ThreadLocalORMSession.flush_all()
            t.update_stats()
        ThreadLocalORMSession.flush_all()
        f.update_stats()
    return warnings

def make_schema(user_name_map, default_username, warnings):
    USER = AlluraUser(user_name_map, default_username, warnings)
    TIMESTAMP = TimeStamp()

    POST = {
        'msg_id':str,
        'is_followup_to':str,
        'is_deleted':str,
        'thread_id':str,
        'poster_name':str,
        'poster_user':USER,
        'subject':str,
        'date':TIMESTAMP,
        'body':str,
        }

    FORUM = {
        'name': str,
        'description': str,
        'threads': { str: [ POST ] },
        }

    result = S.SchemaItem.make({
            'class':str,
            'trackers':[None],
            'forums': { str: FORUM }
            })
    return result

class AlluraUser(S.FancySchemaItem):

    def __init__(self, mapping, default_username, warnings, **kw):
        self.mapping = mapping
        self.default_username = default_username
        self.warnings = warnings
        super(AlluraUser, self).__init__(**kw)

    def _validate(self, value, **kw):
        value = S.String().validate(value)
        sf_username = self.mapping.get(value, value)
        result = M.User.by_username(sf_username)
        if result is None:
            self.warnings.append('User %s not found' % value)
            if callable(self.default_username):
                sf_username = self.default_username(value)
            else:
                sf_username = self.default_username
            self.warnings.append('... setting username to %r' % sf_username)
            result = M.User.by_username(sf_username)
            self.mapping[value] = sf_username
        return result

    def _from_python(self, value, state):
        return value.username

class TimeStamp(S.FancySchemaItem):

    def _validate(self, value, **kwargs):
        try:
            value = int(value)
        except TypeError:
            raise S.Invalid('%s is not int()-able' % value, value, None)
        value = datetime.utcfromtimestamp(value)
        return value

def create_user(json_username):
    allura_username = c.project.shortname + '-' + json_username
    while True:
        try:
            M.User.register(
                dict(
                    username=allura_username,
                    display_name=allura_username),
                False)
            session(M.User).flush()
            break
        except:
            raise
    return allura_username

def create_post(discussion_id, thread_id, json_post):
    p = DM.ForumPost(
        _id='%s@import' % (json_post.msg_id),
        thread_id=thread_id,
        discussion_id=discussion_id,
        timestamp=json_post.date,
        author_id=json_post.poster_user._id,
        text=json_post.body,
        status='ok')
    if json_post.is_followup_to not in ('0', '-1'):
        p.parent_id = '%s@import' % (json_post['is_followup_to'])
    return p
