#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (C) Enrique J. Hernández Blasco <ejhernandez@zentyal.com> 2014
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
"""
Tool to migrate DB schemas using MySQL backend
"""
# TODO: Use argparse when we deprecate python 2.6
import optparse
import sys
import os

# To allow running from the source directory
sys.path.append("python")

from openchange import provision
from openchange.migration import MigrationManager
import samba
from samba.getopt import SambaOptions
from samba.getopt import CredentialsOptions


parser = optparse.OptionParser("openchange_migrate [options] [apps]")
samba_opts = SambaOptions(parser)
parser.add_option_group(samba_opts)
parser.add_option("--openchangedb-uri", type="string",
                  help="openchange database destination by "
                       "specifying a connection string like mysql://user:passwd@host/db_name "
                       "It defaults to the one set in the conf file")
parser.add_option("--indexing-uri", type="string", default=None,
                  help="indexing database destination by specifying "
                       "a connection string. It defaults to the one set in the conf file")
parser.add_option("--named-props-uri", type="string", default=None,
                  help="named properties database destination by specifying "
                       "a connection string. It defaults to the one set in the conf file")
parser.add_option("--target-version", action="store", type="int",
                  help="Indicate which MySQL schema migration to migrate")
parser.add_option("--list", action="store_true",
                  help="List MySQL schema migrations applied in an existing OpenChange installation")
parser.add_option("--fake", action="store_true",
                  help="Fake a migration. Requires to set --target-version")


apps = []
opts, args = parser.parse_args()

all_apps = MigrationManager.apps()
if len(args) == 0:
    apps = all_apps
else:
    apps = args


lp = samba_opts.get_loadparm()

if not apps:
    sys.stderr.write("No defined OpenChange app to migrate\n")
    sys.exit(1)
else:
    for app in apps:
        if not app in all_apps:
            sys.stderr.write(app + " is not a registered application\n")
            sys.stderr.write("Registered applications: " + ', '.join(all_apps) + "\n")
            sys.exit(1)

# Checks over args
if opts.fake and opts.target_version is None:
    sys.stderr.write("No defined --target-version to fake\n")
    sys.exit(2)

if 'directory' in apps:
    print "=== OpenChange Directory ==="
    if opts.list:
        provision.directory_list_migrations(lp, opts.openchangedb_uri)
    elif opts.fake:
        provision.directory_fake_migration(lp, opts.openchangedb_uri, opts.target_version)
    else:
        credopts = CredentialsOptions(parser)
        creds = credopts.get_credentials(lp)
        provisionnames = provision.guess_names_from_smbconf(lp, creds)

        _setupdir = os.path.dirname(__file__)
        if not os.path.exists(os.path.join(_setupdir, "AD")):
            _setupdir = samba.param.setup_dir()

        def setup_path(*args):
            global _setupdir
            return os.path.join(_setupdir, *args)
        kwargs = {
            'lp': lp,
            'credopts': credopts,
            'creds': creds,
            'names': provisionnames,
            'setup_path': setup_path,
        }

        provision.directory_migrate(opts.openchangedb_uri, opts.target_version, **kwargs)


if 'openchangedb' in apps:
    print "=== OpenChange DB ==="
    if opts.list:
        provision.openchangedb_list_migrations(lp, opts.openchangedb_uri)
    elif opts.fake:
        provision.openchangedb_fake_migration(lp, opts.openchangedb_uri, opts.target_version)
    else:
        provision.openchangedb_migrate(lp, opts.openchangedb_uri, opts.target_version)


if 'indexing' in apps:
    print "=== Indexing ==="
    if opts.list:
        provision.indexing_list_migrations(lp, opts.indexing_uri)
    elif opts.fake:
        provision.indexing_fake_migration(lp, opts.indexing_uri, opts.target_version)
    else:
        provision.indexing_migrate(lp, opts.indexing_uri, opts.target_version)


if 'named_properties' in apps:
    print "=== Named Properties ==="
    if opts.list:
        provision.named_props_list_migrations(lp, opts.named_props_uri)
    elif opts.fake:
        provision.named_props_fake_migration(lp, opts.named_props_uri, opts.target_version)
    else:
        provision.named_props_migrate(lp, opts.named_props_uri, opts.target_version)
