# Copyright 2019 The Meson development team

# 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 annotations

from mesonbuild.templates.sampleimpl import SampleImpl
import re


hello_java_template = '''

public class {class_name} {{
    final static String PROJECT_NAME = "{project_name}";

    public static void main (String args[]) {{
        if(args.length != 0) {{
            System.out.println(args + " takes no arguments.");
            System.exit(0);
        }}
        System.out.println("This is project " + PROJECT_NAME + ".");
        System.exit(0);
    }}
}}

'''

hello_java_meson_template = '''project('{project_name}', 'java',
  version : '{version}',
  default_options : ['warning_level=3'])

exe = jar('{exe_name}', '{source_name}',
  main_class : '{exe_name}',
  install : true)

test('basic', exe)
'''

lib_java_template = '''

public class {class_name} {{
    final static int number = 6;

    public final int get_number() {{
      return number;
    }}
}}

'''

lib_java_test_template = '''

public class {class_test} {{
    public static void main (String args[]) {{
        if(args.length != 0) {{
            System.out.println(args + " takes no arguments.");
            System.exit(1);
        }}

        {class_name} c = new {class_name}();
        Boolean result = true;
        System.exit(result.compareTo(c.get_number() != 6));
    }}
}}

'''

lib_java_meson_template = '''project('{project_name}', 'java',
  version : '{version}',
  default_options : ['warning_level=3'])

jarlib = jar('{class_name}', '{source_file}',
  main_class : '{class_name}',
  install : true,
)

test_jar = jar('{class_test}', '{test_source_file}',
  main_class : '{class_test}',
  link_with : jarlib)
test('{test_name}', test_jar)

# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
  include_directories: include_directories('.'),
  link_with : jarlib)
'''


class JavaProject(SampleImpl):
    def __init__(self, options):
        super().__init__()
        self.name = options.name
        self.version = options.version

    def create_executable(self) -> None:
        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
        uppercase_token = lowercase_token.upper()
        class_name = uppercase_token[0] + lowercase_token[1:]
        source_name = uppercase_token[0] + lowercase_token[1:] + '.java'
        open(source_name, 'w', encoding='utf-8').write(
            hello_java_template.format(project_name=self.name,
                                       class_name=class_name))
        open('meson.build', 'w', encoding='utf-8').write(
            hello_java_meson_template.format(project_name=self.name,
                                             exe_name=class_name,
                                             source_name=source_name,
                                             version=self.version))

    def create_library(self) -> None:
        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
        uppercase_token = lowercase_token.upper()
        class_name = uppercase_token[0] + lowercase_token[1:]
        class_test = uppercase_token[0] + lowercase_token[1:] + '_test'
        lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java'
        test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java'
        kwargs = {'utoken': uppercase_token,
                  'ltoken': lowercase_token,
                  'class_test': class_test,
                  'class_name': class_name,
                  'source_file': lib_java_name,
                  'test_source_file': test_java_name,
                  'project_name': self.name,
                  'lib_name': lowercase_token,
                  'test_name': lowercase_token,
                  'version': self.version,
                  }
        open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs))
        open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs))
        open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs))
