# Copyright 2015-2018 Ask Hjorth Larsen, Fawzi Mohamed, Ankit Kariryaa
# 
#   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.

from __future__ import print_function
from subprocess import Popen, PIPE


octtype2nomadtype = {'float': 'f',
                     'integer': 'C', # Integers are really names, generally!
                     'logical': 'b',
                     'block': 'C',
                     'string': 'C',
                     'flag': 'C'}


json_header = """{
  "type": "nomad_meta_info_1_0",
  "description": "autogenerated nomad meta info for octopus parser",
  "dependencies": [ {
      "relativePath": "common.nomadmetainfo.json"
    }],
  "metaInfos": [ %(info)s]
}"""


json_template = """{
      "description": "%(description)s",
      "dtypeStr": "%(dtypeStr)s",
      "name": "%(name)s",
      "repeats": false,
      "shape": [],
      "superNames": [
        "%(supername)s"
      ]
    }"""

json_section_template = """{
      "description": "%(description)s",
      "kindStr": "type_abstract_document_content",
      "name": "%(name)s",
      "superNames": [
        "section_run"
      ]
    }"""



class OctInputVar:
    def __init__(self, name, octtype, section):
        self.name = name
        self.octtype = octtype
        self.section = section

    def _get_json(self, role, supername):
        description = (r'Octopus %s \"%s\" of type \"%s\" in section \"%s\"'
                       % (role, self.name, self.octtype, self.section))
        return json_template % dict(name='%s_%s' % (supername, self.name),
                                    dtypeStr=octtype2nomadtype[self.octtype],
                                    supername=supername,
                                    description=description)

    def get_input_json(self):
        return self._get_json('input parameter', 'x_octopus_input')

    def get_parserlog_json(self):
        return self._get_json('parser log entry', 'x_octopus_parserlog')


def main():
    searchproc = Popen(['oct-help', '--search', ''],
                       stdout=PIPE)

    def normalize(name):
        return var.name.lower() + '.'  # The '.' fiddles with EOL ordering

    oct_vars = {}

    def add(var):
        normalized_name = normalize(var.name)
        if normalized_name not in oct_vars:
            oct_vars[normalized_name] = var

    for line in searchproc.stdout.readlines():
        name = line.strip()
        printproc = Popen(('oct-help --print %s' % name).split(),
                          stdout=PIPE)
        fd = printproc.stdout

        # Example of output from oct-help:
        # ------------------
        #Variable: Spacing
        #Type:     float
        #Section:  Mesh
        #Description:
        #  The spacing between the points in the mesh. This controls the
        #  quality of the discretization: smaller spacing gives more precise
        #  results but increased computational cost.
        #  (.......)
        #------------------

        allowed_vardata = set(['Variable', 'Type', 'Default', 'Section'])

        vardata = {}
        for line in fd:
            title, remainder = line.split(':', 1)
            if title == 'Description':
                break
            vardata[title] = remainder.strip()

        var = OctInputVar(vardata.get('Variable'),
                          vardata.get('Type'),
                          vardata.get('Section'))

        add(var)

    itokens = []
    ptokens = []
    for key in sorted(oct_vars):
        var = oct_vars[key]
        itokens.append(var.get_input_json())
        ptokens.append(var.get_parserlog_json())

    itokens.append(json_section_template
                   % dict(description='section describing Octopus input '
                          'parameters',
                          name='x_octopus_input'))
    ptokens.append(json_section_template
                   % dict(description='section describing Octopus inputfile '
                          'parser log output',
                          name='x_octopus_parserlog'))

    print(json_header % dict(info=', '.join(itokens + ptokens)))

if __name__ == '__main__':
    main()
