# Path: animanager/datets.py
# def to_ts(date: datetime.date) -> float:
# def to_date(ts: float) -> datetime.date:
# 
# Path: animanager/sqlite/utils.py
# def upsert(db, table, key_cols, update_dict):
#     """Fabled upsert for SQLiteDB.
# 
#     Perform an upsert based on primary key.
# 
#     :param SQLiteDB db: database
#     :param str table: table to upsert into
#     :param str key_cols: name of key columns
#     :param dict update_dict: key-value pairs to upsert
# 
#     """
#     with db:
#         cur = db.cursor()
#         cur.execute(
#             'UPDATE {} SET {} WHERE {}'.format(
#                 table,
#                 ','.join(_sqlpformat(col) for col in update_dict.keys()),
#                 ' AND '.join(_sqlpformat(col) for col in key_cols),
#             ),
#             update_dict,
#         )
#         if db.changes() == 0:
#             keys, values = zip(*update_dict.items())
#             cur.execute(
#                 'INSERT INTO {} ({}) VALUES ({})'.format(
#                     table,
#                     ','.join(keys),
#                     ','.join('?' for _ in values)),
#                 values)
# 
# Path: animanager/db/query/eptype.py
# def get_eptype(db, name):
#     """Get episode type by name or id."""
#     return EpisodeTypes.from_db(db)[name]
# 
# Path: animanager/db/query/select.py
# ALL = 1
# 
# def lookup(
#         db,
#         aid: int,
#         fields: FieldsParam = ALL,
#         episode_fields: FieldsParam = (),
# ) -> Anime:
#     """Look up information for a single anime.
# 
#     :param fields: anime fields to get.  If ``None``, get all fields.
#     :param episode_fields: episode fields to get.
#         If ``None``, get all fields.  If empty, don't get episodes.
# 
#     """
#     return next(select(
#         db,
#         'aid=?',
#         (aid,),
#         fields=fields,
#         episode_fields=episode_fields,
#     ))
# 
# Path: animanager/db/query/status.py
# def cache_status(db, aid, force=False):
#     """Calculate and cache status for given anime.
# 
#     Don't do anything if status already exists and force is False.
# 
#     """
#     with db:
#         cur = db.cursor()
#         if not force:
#             # We don't do anything if we already have this aid in our
#             # cache.
#             cur.execute('SELECT 1 FROM cache_anime WHERE aid=?', (aid,))
#             if cur.fetchone() is not None:
#                 return
# 
#         # Retrieve information for determining complete.
#         cur.execute(
#             'SELECT episodecount, enddate FROM anime WHERE aid=?', (aid,))
#         row = cur.fetchone()
#         if row is None:
#             raise ValueError('aid provided does not exist')
#         episodecount, enddate = row
# 
#         # Select all regular episodes in ascending order.
#         cur.execute("""
#             SELECT number, user_watched FROM episode
#             WHERE aid=? AND type=?
#             ORDER BY number ASC
#             """, (aid, get_eptype(db, 'regular').id))
# 
#         # We find the last consecutive episode that is user_watched.
#         number = 0
#         for number, watched in cur:
#             # Once we find the first unwatched episode, we set the last
#             # consecutive watched episode to the previous episode (or 0).
#             if watched == 0:
#                 number -= 1
#                 break
#         # We store this in the cache.
#         set_status(db, aid, enddate and episodecount <= number, number)
# 
# def set_status(
#         db,
#         aid: int,
#         complete: Any,
#         watched_episodes: int,
# ) -> None:
#     """Set anime status."""
#     upsert(db, 'cache_anime', ['aid'], {
#         'aid': aid,
#         'complete': 1 if complete else 0,
#         'watched_episodes': watched_episodes,
#     })


import logging
from animanager import datets
from animanager.sqlite.utils import upsert
from .eptype import get_eptype
from .select import ALL, lookup
from .status import cache_status, set_status
# Animanager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Animanager.  If not, see <http://www.gnu.org/licenses/>.




logger = logging.getLogger(__name__)


def add(db, anime):
    """Add an anime (or update existing).

    anime is an AnimeTree instance.

    """
    aid = anime.aid
    values = {
        'aid': aid,
        'title': anime.title,
        'type': anime.type,
        'episodecount': anime.episodecount,
    }
    if anime.startdate is not None:
        values['startdate'] = datets.to_ts(anime.startdate)
    if anime.enddate is not None:

# Path: animanager/datets.py
# def to_ts(date: datetime.date) -> float:
# def to_date(ts: float) -> datetime.date:
# 
# Path: animanager/sqlite/utils.py
# def upsert(db, table, key_cols, update_dict):
#     """Fabled upsert for SQLiteDB.
# 
#     Perform an upsert based on primary key.
# 
#     :param SQLiteDB db: database
#     :param str table: table to upsert into
#     :param str key_cols: name of key columns
#     :param dict update_dict: key-value pairs to upsert
# 
#     """
#     with db:
#         cur = db.cursor()
#         cur.execute(
#             'UPDATE {} SET {} WHERE {}'.format(
#                 table,
#                 ','.join(_sqlpformat(col) for col in update_dict.keys()),
#                 ' AND '.join(_sqlpformat(col) for col in key_cols),
#             ),
#             update_dict,
#         )
#         if db.changes() == 0:
#             keys, values = zip(*update_dict.items())
#             cur.execute(
#                 'INSERT INTO {} ({}) VALUES ({})'.format(
#                     table,
#                     ','.join(keys),
#                     ','.join('?' for _ in values)),
#                 values)
# 
# Path: animanager/db/query/eptype.py
# def get_eptype(db, name):
#     """Get episode type by name or id."""
#     return EpisodeTypes.from_db(db)[name]
# 
# Path: animanager/db/query/select.py
# ALL = 1
# 
# def lookup(
#         db,
#         aid: int,
#         fields: FieldsParam = ALL,
#         episode_fields: FieldsParam = (),
# ) -> Anime:
#     """Look up information for a single anime.
# 
#     :param fields: anime fields to get.  If ``None``, get all fields.
#     :param episode_fields: episode fields to get.
#         If ``None``, get all fields.  If empty, don't get episodes.
# 
#     """
#     return next(select(
#         db,
#         'aid=?',
#         (aid,),
#         fields=fields,
#         episode_fields=episode_fields,
#     ))
# 
# Path: animanager/db/query/status.py
# def cache_status(db, aid, force=False):
#     """Calculate and cache status for given anime.
# 
#     Don't do anything if status already exists and force is False.
# 
#     """
#     with db:
#         cur = db.cursor()
#         if not force:
#             # We don't do anything if we already have this aid in our
#             # cache.
#             cur.execute('SELECT 1 FROM cache_anime WHERE aid=?', (aid,))
#             if cur.fetchone() is not None:
#                 return
# 
#         # Retrieve information for determining complete.
#         cur.execute(
#             'SELECT episodecount, enddate FROM anime WHERE aid=?', (aid,))
#         row = cur.fetchone()
#         if row is None:
#             raise ValueError('aid provided does not exist')
#         episodecount, enddate = row
# 
#         # Select all regular episodes in ascending order.
#         cur.execute("""
#             SELECT number, user_watched FROM episode
#             WHERE aid=? AND type=?
#             ORDER BY number ASC
#             """, (aid, get_eptype(db, 'regular').id))
# 
#         # We find the last consecutive episode that is user_watched.
#         number = 0
#         for number, watched in cur:
#             # Once we find the first unwatched episode, we set the last
#             # consecutive watched episode to the previous episode (or 0).
#             if watched == 0:
#                 number -= 1
#                 break
#         # We store this in the cache.
#         set_status(db, aid, enddate and episodecount <= number, number)
# 
# def set_status(
#         db,
#         aid: int,
#         complete: Any,
#         watched_episodes: int,
# ) -> None:
#     """Set anime status."""
#     upsert(db, 'cache_anime', ['aid'], {
#         'aid': aid,
#         'complete': 1 if complete else 0,
#         'watched_episodes': watched_episodes,
#     })


# Path: animanager/db/query/update.py
import logging
from animanager import datets
from animanager.sqlite.utils import upsert
from .eptype import get_eptype
from .select import ALL, lookup
from .status import cache_status, set_status

# Animanager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Animanager.  If not, see <http://www.gnu.org/licenses/>.




logger = logging.getLogger(__name__)


def add(db, anime):
    """Add an anime (or update existing).

    anime is an AnimeTree instance.

    """
    aid = anime.aid
    values = {
        'aid': aid,
        'title': anime.title,
        'type': anime.type,
        'episodecount': anime.episodecount,
    }
    if anime.startdate is not None:
        values['startdate'] = datets.to_ts(anime.startdate)
    if anime.enddate is not None:

        values['enddate'] = datets.to_ts(anime.enddate)