#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
#    LinOTP - the open source solution for two factor authentication
#    Copyright (C) 2010 - 2019 KeyIdentity GmbH
#
#    This file is part of LinOTP server.
#
#    This program is free software: you can redistribute it and/or
#    modify it under the terms of the GNU Affero General Public
#    License, version 3, as published by the Free Software Foundation.
#
#    This program 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 Affero General Public License for more details.
#
#    You should have received a copy of the
#               GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#    E-mail: linotp@keyidentity.com
#    Contact: www.linotp.org
#    Support: www.keyidentity.com
#
"""This tool reads the token number from the token database."""

from linotp.lib.utils import config_get, INI_FILE
from sqlalchemy import *
from sqlalchemy.sql import text as sql_text
from getopt import getopt, GetoptError
import sys, datetime
import logging, logging.config
logging.config.fileConfig(INI_FILE)
log = logging.getLogger(__name__)

from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql.expression import column
import socket
import re

def token_usage(SQL_URL, AUDIT_URL, AUDIT_PREFIX):
    t1 = datetime.datetime.now()
    id_pos = 0
    engine = create_engine(SQL_URL)

    # set this to True, if you want to see the SQL statements
    # that are created
    engine.echo = False
    metadata = MetaData(engine)

    # The audit table already exists, so no need to redefine it. Just
    # load it from the database using the "autoload" feature.
    token = Table('Token', metadata, autoload=True)

    overall_number = 0
    not_assigned = 0
    not_active = 0

    # overall
    rows = token.count().execute()
    row = rows.fetchone()
    overall_number = int(row[id_pos])

    # not assigned tokens
    rows = token.count().where(sql_text("LinOtpUserid=''")).execute()
    row = rows.fetchone()
    not_assigned = int(row[id_pos])

    # disabled tokens
    rows = token.count().where(sql_text("LinOtpIsactive=0")).execute()
    row = rows.fetchone()
    not_active = int(row[id_pos])

    print "Token statistics"
    print "=============================="
    print "Hostname:\t\t%s" % socket.gethostname()
    print "Date:\t\t\t%s" % t1
    print "Overall Token number:\t%i " % overall_number
    print "Active Tokens: \t\t%i" % (overall_number - not_active)
    print "Not Assigned Tokens:\t%i " % not_assigned
    print "Inactive Tokens:\t%i " % not_active


    print
    print "Tokens per month"
    print "================"
    # The audit table already exists, so no need to redefine it. Just
    # load it from the database using the "autoload" feature.
    audit = Table('%saudit' % AUDIT_PREFIX, metadata, autoload=True)
    rows = audit.select(sql_text("action_detail like '%tokennum%'"),
                        order_by=column("id").desc()).execute()

    current_month = None
    min_token = None
    max_token = None
    for row in rows:
        month = None
        m = re.match("(\d\d\d\d-\d\d)-\d\d.*", row.timestamp)
        if m:
            month = m.group(1)
        if month != current_month:
            if max_token:
                print "maximum token: %i" % max_token
            if min_token:
                print "minimum token: %i" % min_token
            # this is a new month
            current_month = month
            min_token = None
            max_token = None
            print "Month %s" % current_month
            print "----------------------"

        tnum = None
        m = re.match("tokennum = (\d*)", row.action_detail)
        if m:
            tnum = int(m.group(1))
            if not min_token or tnum < min_token:
                min_token = tnum
            if not max_token or tnum > max_token:
                max_token = tnum

    if max_token:
        print "maximum token: %i" % max_token
    if min_token:
        print "minimum token: %i" % min_token

    return

def main():

    AUDIT_URL = config_get("DEFAULT", "linotpAudit.sql.url")
    SQL_URL = config_get("app:main", "sqlalchemy.url")
    AUDIT_PREFIX = config_get("DEFAULT" , "linotpAudit.sql.table_prefix") or ""

    token_usage(SQL_URL, AUDIT_URL, AUDIT_PREFIX)

    sys.exit(0)

if __name__ == '__main__':
    main()
