#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import json
from optparse import OptionParser

from allura.lib.import_api import AlluraImportApiClient
from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki


def main():
    optparser, options, args = parse_options()

    import_options = {}
    for s in options.import_opts:
        k, v = s.split('=', 1)
        if v == 'false':
            v = False
        import_options[k] = v

    user_map = {}
    if options.user_map_file:
        f = open(options.user_map_file)
        try:
            user_map = json.load(f)
            if type(user_map) is not type({}):
                raise ValueError
            for k, v in user_map.iteritems():
                print k, v
                if not isinstance(k, basestring) or not isinstance(v, basestring):
                    raise ValueError
        except ValueError:
            optparser.error(
                '--user-map should specify JSON file with format {"original_user": "sf_user", ...}')
        finally:
            f.close()

    import_options['user_map'] = user_map

    cli = AlluraImportApiClient(options.base_url, options.token, options.verbose)
    doc_txt = open(args[0]).read()

    if options.forum:
        import_forum(cli, options.project, options.forum, user_map, doc_txt,
                     validate=options.validate, neighborhood=options.neighborhood)
    elif options.wiki:
        import_wiki(cli, options.project, options.wiki, options, doc_txt)



def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
        neighborhood='p'):
    url = '/rest/{neighborhood}/{project}/{tool}'.format(
            neighborhood=neighborhood,
            project=project,
            tool=tool,
            )
    if validate:
        url += '/validate_import'
        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
    else:
        url += '/perform_import'
        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))


def parse_options():
    optparser = OptionParser(usage='''%prog [options] <JSON dump>

Import project data dump in JSON format into an Allura project.''')
    optparser.add_option('-t', '--token', dest='token',
                         help='OAuth bearer token (generate at /auth/oauth/)')
    optparser.add_option('-p', '--project', dest='project',
                         help='Project to import to')
    optparser.add_option('-n', '--neighborhood', dest='neighborhood',
                         help="URL prefix of destination neighborhood (default is 'p')",
                         default='p')
    optparser.add_option('-f', '--forum', dest='forum',
                         help='Forum tool to import to')
    optparser.add_option('-w', '--wiki', dest='wiki',
                         help='Wiki tool to import to')
    optparser.add_option('-u', '--base-url', dest='base_url',
                         default='https://sourceforge.net', help='Base Allura URL (%default)')
    optparser.add_option('-o', dest='import_opts',
                         default=[], action='append', help='Specify import option(s)', metavar='opt=val')
    optparser.add_option('--user-map', dest='user_map_file',
                         help='Map original users to SF.net users', metavar='JSON_FILE')
    optparser.add_option('--validate', dest='validate',
                         action='store_true', help='Validate import data')
    optparser.add_option('-v', '--verbose', dest='verbose',
                         action='store_true', help='Verbose operation')
    optparser.add_option('-c', '--continue', dest='cont',
                         action='store_true', help='Continue import into existing tracker')
    options, args = optparser.parse_args()
    if len(args) != 1:
        optparser.error("Wrong number of arguments")
    if not options.token:
        optparser.error("OAuth bearer token is required")
    if not options.project:
        optparser.error("Target project is required")
    options.neighborhood = options.neighborhood.strip('/')
    return optparser, options, args


if __name__ == '__main__':
    main()
