#!/usr/bin/env python
# Licensed 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 os
import subprocess
import textwrap

BASEDIR = os.path.split(os.path.realpath(__file__))[0] + "/../../"


if __name__ == "__main__":
    os.chdir(BASEDIR)
    opt_file = open("cinder/opts.py", 'w')
    opt_dict = {}
    dir_trees_list = []
    REGISTER_OPTS_STR = "CONF.register_opts("
    REGISTER_OPT_STR = "CONF.register_opt("

    license_str = textwrap.dedent(
        """
        # Licensed 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.\n
    """)
    opt_file.write(license_str)

    opt_file.write("import itertools\n\n")

    targetdir = 'cinder'

    common_string = ('find ' + targetdir + ' -type f -name "*.py" !  '
                     '-path "*/tests/*" -exec grep -l "%s" {} '
                     '+  | sed -e "s|^' + BASEDIR +
                     '|/|g" | sort -u')

    cmd_opts = common_string % REGISTER_OPTS_STR
    output_opts = subprocess.check_output('{}'.format(cmd_opts), shell = True)
    dir_trees_list = output_opts.split()

    cmd_opt = common_string % REGISTER_OPT_STR
    output_opt = subprocess.check_output('{}'.format(cmd_opt), shell = True)
    temp_list = output_opt.split()

    for item in temp_list:
        dir_trees_list.append(item)
    dir_trees_list.sort()

    flag = False

    def _check_import(aline):
        if len(aline) > 79:
            new_lines = aline.partition(' as ')
            return new_lines
        else:
            return [aline]

    for atree in dir_trees_list:

        if atree in ["cinder/config/generate_cinder_opts.py",
                     "cinder/hacking/checks.py",
                     "cinder/volume/configuration.py",
                     "cinder/test.py"]:
            continue

        dirs_list = atree.split('/')

        import_module = "from "
        init_import_module = ""
        import_name = ""

        for dir in dirs_list:
            if dir.find(".py") == -1:
                import_module += dir + "."
                init_import_module += dir + "."
                import_name += dir + "_"
            else:
                if dir[:-3] != "__init__":
                    import_name += dir[:-3].replace("_", "")
                    import_module = (import_module[:-1] + " import " +
                                     dir[:-3] + " as " + import_name)
                    lines = _check_import(import_module)
                    if len(lines) > 1:
                        opt_file.write(lines[0] + lines[1] + "\\\n")
                        opt_file.write("    " + lines[2] + "\n")
                    else:
                        opt_file.write(lines[0] + "\n")

                else:
                    import_name = import_name[:-1].replace('/', '.')
                    init_import = atree[:-12].replace('/', '.')
                    opt_file.write("import " + init_import + "\n")

                    flag = True
        if flag is False:
            opt_dict[import_name] = atree
        else:
            opt_dict[init_import_module.strip(".")] = atree

        flag = False

    registered_opts_dict = {'DEFAULT': [], }

    def _write_item(opts):
        list_name = opts[-3:]
        if list_name.lower() == "opt":
            line_to_write = "                [" + opts.strip("\n") + "],\n"
            opt_line = _check_line_length(line_to_write)
            if len(opt_line) > 1:
                opt_file.write(opt_line[0] + opt_line[1] + "\n")
                opt_file.write("                    " + opt_line[2])
            else:
                opt_file.write(opt_line[0])
        else:
            line_to_write = "                " + opts.strip("\n") + ",\n"
            opt_line = _check_line_length(line_to_write)
            if len(opt_line) > 1:
                opt_file.write(opt_line[0] + opt_line[1] + "\n")
                opt_file.write("                " + opt_line[2])
            else:
                opt_file.write(opt_line[0])

    def _retrieve_name(aline):
        if REGISTER_OPT_STR in aline:
            str_to_replace = REGISTER_OPT_STR
        else:
            str_to_replace = REGISTER_OPTS_STR
        return aline.replace(str_to_replace, "")

    def _check_line_length(aline):
        if len(aline) > 79:
            temp = aline.split(".")
            lines_to_write = []

            for section in temp:
                lines_to_write.append(section)
                lines_to_write.append('.')

            return lines_to_write

        else:
            return [aline]

    for key in opt_dict:
        fd = os.open(opt_dict[key], os.O_RDONLY)
        afile = os.fdopen(fd, "r")

        for aline in afile:
            exists = aline.find("CONF.register_opt")
            if exists != -1:
                # TODO(kjnelson) FIX THIS LATER. These are instances where
                # CONF.register_opts is happening without actually registering
                # real lists of opts

                exists = aline.find('base_san_opts')
                if (exists != -1) or (key == 'cinder_volume_configuration'):
                    continue

                group_exists = aline.find(', group=')
                formatted_opt = _retrieve_name(aline[: group_exists])
                formatted_opt = formatted_opt.replace(')', '').strip()
                if group_exists != -1:
                    group_name = aline[group_exists:-1].replace(', group=\"\'', '').\
                        replace(', group=', '').strip("\'\")").upper()
                    if group_name in registered_opts_dict:
                        line = key + "." + formatted_opt
                        registered_opts_dict[group_name].append(line)
                    else:
                        line = key + "." + formatted_opt
                        registered_opts_dict[group_name] = [line]
                else:
                    line = key + "." + formatted_opt
                    registered_opts_dict['DEFAULT'].append(line)

setup_str = ("\n\n"
             "def list_opts():\n"
             "    return [\n")
opt_file.write(setup_str)

for key in registered_opts_dict:
    section_start_str = ("        ('" + key + "',\n"
                         "            itertools.chain(\n")
    opt_file.write(section_start_str)
    for item in registered_opts_dict[key]:
        _write_item(item)
    section_end_str = "            )),\n"
    opt_file.write(section_end_str)

closing_str = ("    ]\n")
opt_file.write(closing_str)
opt_file.close()
