# -*- coding: utf-8 -*-
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
from datetime import datetime
import os.path
import sqlite3
from django.core.management.base import BaseCommand

from api.helpers import timestamp
from api.settings import MOBILE_INIT_DB
from catalogue.models import Book, Tag
from wolnelektury.utils import makedirs


class Command(BaseCommand):
    help = 'Creates an initial SQLite file for the mobile app.'

    def handle(self, **options):
        # those should be versioned
        last_checked = timestamp(datetime.now())
        db = init_db(last_checked)
        for b in Book.objects.all():
            add_book(db, b)
        for t in Tag.objects.exclude(
                category__in=('book', 'set', 'theme')).exclude(items=None):
            # only add non-empty tags
            add_tag(db, t)
        db.commit()
        db.close()
        current(last_checked)


def pretty_size(size):
    """ Turns size in bytes into a prettier string.

        >>> pretty_size(100000)
        '97 KiB'
    """
    if not size:
        return None
    units = ['B', 'KiB', 'MiB', 'GiB']
    size = float(size)
    unit = units.pop(0)
    while size > 1000 and units:
        size /= 1024
        unit = units.pop(0)
    if size < 10:
        return "%.1f %s" % (size, unit)
    return "%d %s" % (size, unit)
    #
    # if not isinstance(value, unicode):
    #     value = unicode(value, 'utf-8')
    #
    # # try to replace chars
    # value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value)
    # value = value.lower()
    # value = re.sub(r'[^a-z0-9{|}]+', '~', value)
    #
    # return value.encode('ascii', 'ignore')


def init_db(last_checked):
    makedirs(MOBILE_INIT_DB)
    db = sqlite3.connect(os.path.join(MOBILE_INIT_DB, 'initial.db-%d' % last_checked))

    schema = """
CREATE TABLE book (
    id INTEGER PRIMARY KEY, 
    title VARCHAR,
    cover VARCHAR,
    html_file VARCHAR, 
    html_file_size INTEGER, 
    parent INTEGER,
    parent_number INTEGER,

    sort_key VARCHAR,
    pretty_size VARCHAR,
    authors VARCHAR,
    _local BOOLEAN
);
CREATE INDEX IF NOT EXISTS book_title_index ON book (sort_key);
CREATE INDEX IF NOT EXISTS book_title_index ON book (title);
CREATE INDEX IF NOT EXISTS book_parent_index ON book (parent);

CREATE TABLE tag (
    id INTEGER PRIMARY KEY, 
    name VARCHAR, 
    category VARCHAR, 
    sort_key VARCHAR, 
    books VARCHAR);
CREATE INDEX IF NOT EXISTS tag_name_index ON tag (name);
CREATE INDEX IF NOT EXISTS tag_category_index ON tag (category);
CREATE INDEX IF NOT EXISTS tag_sort_key_index ON tag (sort_key);

CREATE TABLE state (last_checked INTEGER);
"""

    db.executescript(schema)
    db.execute("INSERT INTO state VALUES (:last_checked)", {'last_checked': last_checked})
    return db


def current(last_checked):
    target = os.path.join(MOBILE_INIT_DB, 'initial.db')
    if os.path.lexists(target):
        os.unlink(target)
    os.symlink(
        'initial.db-%d' % last_checked,
        target,
    )


book_sql = """
    INSERT INTO book 
        (id, title, cover, html_file,  html_file_size, parent, parent_number, sort_key, pretty_size, authors) 
    VALUES 
        (:id, :title, :cover, :html_file, :html_file_size, :parent, :parent_number, :sort_key, :size_str, :authors);
"""
book_tag_sql = "INSERT INTO book_tag (book, tag) VALUES (:book, :tag);"
tag_sql = """
    INSERT INTO tag
        (id, category, name, sort_key, books)
    VALUES
        (:id, :category, :name, :sort_key, :book_ids);
"""
categories = {'author': 'autor',
              'epoch': 'epoka',
              'genre': 'gatunek',
              'kind': 'rodzaj',
              'theme': 'motyw'
              }


def add_book(db, book):
    if book.html_file:
        html_file = book.html_file.url
        html_file_size = book.html_file.size
    else:
        html_file = html_file_size = None
    db.execute(book_sql, {
        'title': book.title,
        'cover': book.cover.url if book.cover else None,
        'html_file': html_file,
        'html_file_size': html_file_size,
        'parent': book.parent_id,
        'parent_number': book.parent_number,
        'sort_key': book.sort_key,
        'size_str': pretty_size(html_file_size),
        'authors': book.author_unicode(),
    })


def add_tag(db, tag):
    books = Book.tagged_top_level([tag])
    book_ids = ','.join(str(book_id) for book_id in books.values_list('id', flat=True))
    db.execute(tag_sql, {
        'category': categories[tag.category],
        'name': tag.name,
        'sort_key': tag.sort_key,
        'book_ids': book_ids,
    })
