#!/usr/bin/env python3
#coding: utf-8

"""
Copyright (c) 2021 Huawei Device Co., Ltd.
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.
Description: Generate interface to get java plugin's js code and binary
"""

import os
import subprocess
import argparse

JAVA_FILE_SUFFIX = "JsCode"
JS_BIN_EXT = ".abc"
ARRAY_MAX = 8192  # size of 8K


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--node",
                        help="path to nodejs exetuable")
    parser.add_argument("--frontend-tool-path",
                        help="path to frontend conversion tool")
    parser.add_argument("--node-modules",
                        help='path to node-modules exetuable')
    parser.add_argument("--plugin-path",
                        help="plugin js file path")
    parser.add_argument("--plugin-name",
                        help="name of js file, ex: BatteryPlugin.js")
    parser.add_argument("--generated-file",
                        help="name of generated file")
    parser.add_argument("--package-name",
                        help="name of generated file's package")

    arguments = parser.parse_args()
    return arguments


def split_array_by_n(array, max_len):
    for i in range(0, len(array), max_len):
        yield array[i: i + max_len]


def gen_bin_info(input_arguments):
    file_name = input_arguments.plugin_name
    file_path = input_arguments.plugin_path
    js_file = os.path.join(file_path, file_name)
    file_name_pre = os.path.splitext(file_name)[0]

    generate_js_bytecode = os.path.join(
        os.path.dirname(__file__), "generate_js_bytecode.py")

    (out_dir, _) = os.path.split(input_arguments.generated_file)
    dst_file = os.path.join(out_dir, f'{file_name_pre}{JS_BIN_EXT}')

    args = [
        '--src-js',
        js_file,
        '--dst-file',
        dst_file,
        '--node',
        input_arguments.node,
        '--frontend-tool-path',
        input_arguments.frontend_tool_path,
        '--node-modules',
        input_arguments.node_modules,
    ]

    proc = subprocess.Popen(['python3', generate_js_bytecode] + args)
    return_code = proc.wait()
    return return_code


def gen_java_method(input_arguments):

    file_name = input_arguments.plugin_name
    file_path = input_arguments.plugin_path
    out_file = input_arguments.generated_file

    file_name_pre = os.path.splitext(file_name)[0]
    js_src_file = os.path.join(file_path, file_name)
    (out_dir, _) = os.path.split(input_arguments.generated_file)
    js_bin_file = os.path.join(out_dir, file_name_pre + JS_BIN_EXT)

    with open(out_file, "w") as output:
        output.write("/*%s * Generated from Java and JavaScript plugins by ts2abc.%s */%s%s"
                     % (os.linesep, os.linesep, os.linesep, os.linesep))

        output.write("package %s;%s"
                     % (input_arguments.package_name, os.linesep))
        output.write("%s" % os.linesep)
        output.write("public class %s%s {%s"
                     % (file_name_pre, JAVA_FILE_SUFFIX, os.linesep))

        # write method: getJsCode
        with open(js_src_file, "r") as input_src:
            output.write("    public static String getJsCode() {%s"
                         % os.linesep)
            output.write("        return%s" % os.linesep)
            lines = input_src.readlines()
            for line in lines[:-1]:
                line = line.strip(os.linesep)
                line = line.replace("\"", "\\\"")
                output.write("        \"%s\\n\" +%s" % (line, os.linesep))

            last_line = lines[-1].replace("\"", "\\\"").strip(os.linesep)
            output.write("        \"%s\";%s" % (last_line, os.linesep))
            output.write("    }%s" % os.linesep)

        output.write("%s" % os.linesep)

        # write method: getJsBytecode
        with open(js_bin_file, "rb") as input_bin:
            # seperate bytecode list
            buf = bytearray(os.path.getsize(js_bin_file))
            input_bin.readinto(buf)
            hex_str = [hex(i) for i in buf]
            byte_str = ["(byte)" + i for i in hex_str]
            seperate_array = split_array_by_n(byte_str, ARRAY_MAX)

            # generate seperate methods for js bytecode with ARRAY_MAX
            method_idx = 0
            method_len_list = []
            for array in seperate_array:
                output.write("    private static byte[] getJsByteCode_%s() {%s"
                             % (method_idx, os.linesep))
                output.write("        return new byte[] {")
                output.write(", ".join(array))
                output.write("};%s" % os.linesep)
                output.write("    }%s" % os.linesep)
                method_idx = method_idx + 1
                method_len_list.append(len(array))

            # generate a method collect all seperated arrays
            cur_pos = 0
            output.write("    public static byte[] getJsByteCode() {%s"
                         % os.linesep)
            output.write("        byte[] allByteCode = new byte[%s];%s"
                         % (len(byte_str), os.linesep))
            for idx, method_len in enumerate(method_len_list):
                output.write("        System.arraycopy(getJsByteCode_%s(), "
                             "0, allByteCode, %s, %s);%s"
                             % (idx, cur_pos, method_len, os.linesep))
                cur_pos = cur_pos + method_len
            output.write("        return allByteCode;%s" % os.linesep)
            output.write("    }%s" % os.linesep)

        output.write("}")


def operate_file(input_arguments):
    retcode = gen_bin_info(input_arguments)
    if retcode != 0:
        return

    gen_java_method(input_arguments)


if __name__ == "__main__":
    operate_file(parse_args())

#!/usr/bin/env python3
#coding: utf-8

"""
Copyright (c) 2021 Huawei Device Co., Ltd.
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.
Description: Generate interface to get java plugin's js code and binary
"""

import os
import subprocess
import argparse

JAVA_FILE_SUFFIX = "JsCode"
JS_BIN_EXT = ".abc"
ARRAY_MAX = 8192  # size of 8K


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--node",
                        help="path to nodejs exetuable")
    parser.add_argument("--frontend-tool-path",
                        help="path to frontend conversion tool")
    parser.add_argument("--node-modules",
                        help='path to node-modules exetuable')
    parser.add_argument("--plugin-path",
                        help="plugin js file path")
    parser.add_argument("--plugin-name",
                        help="name of js file, ex: BatteryPlugin.js")
    parser.add_argument("--generated-file",
                        help="name of generated file")
    parser.add_argument("--package-name",
                        help="name of generated file's package")

    arguments = parser.parse_args()
    return arguments


def split_array_by_n(array, max_len):
    for i in range(0, len(array), max_len):
        yield array[i: i + max_len]


def gen_bin_info(input_arguments):
    file_name = input_arguments.plugin_name
    file_path = input_arguments.plugin_path
    js_file = os.path.join(file_path, file_name)
    file_name_pre = os.path.splitext(file_name)[0]

    generate_js_bytecode = os.path.join(
        os.path.dirname(__file__), "generate_js_bytecode.py")

    (out_dir, _) = os.path.split(input_arguments.generated_file)
    dst_file = os.path.join(out_dir, f'{file_name_pre}{JS_BIN_EXT}')

    args = [
        '--src-js',
        js_file,
        '--dst-file',
        dst_file,
        '--node',
        input_arguments.node,
        '--frontend-tool-path',
        input_arguments.frontend_tool_path,
        '--node-modules',
        input_arguments.node_modules,
    ]

    proc = subprocess.Popen(['python3', generate_js_bytecode] + args)
    return_code = proc.wait()
    return return_code


def gen_java_method(input_arguments):

    file_name = input_arguments.plugin_name
    file_path = input_arguments.plugin_path
    out_file = input_arguments.generated_file

    file_name_pre = os.path.splitext(file_name)[0]
    js_src_file = os.path.join(file_path, file_name)
    (out_dir, _) = os.path.split(input_arguments.generated_file)
    js_bin_file = os.path.join(out_dir, file_name_pre + JS_BIN_EXT)

    with open(out_file, "w") as output:
        output.write("/*%s * Generated from Java and JavaScript plugins by ts2abc.%s */%s%s"
                     % (os.linesep, os.linesep, os.linesep, os.linesep))

        output.write("package %s;%s"
                     % (input_arguments.package_name, os.linesep))
        output.write("%s" % os.linesep)
        output.write("public class %s%s {%s"
                     % (file_name_pre, JAVA_FILE_SUFFIX, os.linesep))

        # write method: getJsCode
        with open(js_src_file, "r") as input_src:
            output.write("    public static String getJsCode() {%s"
                         % os.linesep)
            output.write("        return%s" % os.linesep)
            lines = input_src.readlines()
            for line in lines[:-1]:
                line = line.strip(os.linesep)
                line = line.replace("\"", "\\\"")
                output.write("        \"%s\\n\" +%s" % (line, os.linesep))

            last_line = lines[-1].replace("\"", "\\\"").strip(os.linesep)
            output.write("        \"%s\";%s" % (last_line, os.linesep))
            output.write("    }%s" % os.linesep)

        output.write("%s" % os.linesep)

        # write method: getJsBytecode
        with open(js_bin_file, "rb") as input_bin:
            # seperate bytecode list
            buf = bytearray(os.path.getsize(js_bin_file))
            input_bin.readinto(buf)
            hex_str = [hex(i) for i in buf]
            byte_str = ["(byte)" + i for i in hex_str]
            seperate_array = split_array_by_n(byte_str, ARRAY_MAX)

            # generate seperate methods for js bytecode with ARRAY_MAX
            method_idx = 0
            method_len_list = []
            for array in seperate_array:
                output.write("    private static byte[] getJsByteCode_%s() {%s"
                             % (method_idx, os.linesep))
                output.write("        return new byte[] {")
                output.write(", ".join(array))
                output.write("};%s" % os.linesep)
                output.write("    }%s" % os.linesep)
                method_idx = method_idx + 1
                method_len_list.append(len(array))

            # generate a method collect all seperated arrays
            cur_pos = 0
            output.write("    public static byte[] getJsByteCode() {%s"
                         % os.linesep)
            output.write("        byte[] allByteCode = new byte[%s];%s"
                         % (len(byte_str), os.linesep))
            for idx, method_len in enumerate(method_len_list):
                output.write("        System.arraycopy(getJsByteCode_%s(), "
                             "0, allByteCode, %s, %s);%s"
                             % (idx, cur_pos, method_len, os.linesep))
                cur_pos = cur_pos + method_len
            output.write("        return allByteCode;%s" % os.linesep)
            output.write("    }%s" % os.linesep)

        output.write("}")


def operate_file(input_arguments):
    retcode = gen_bin_info(input_arguments)
    if retcode != 0:
        return

    gen_java_method(input_arguments)


if __name__ == "__main__":
    operate_file(parse_args())

#!/usr/bin/env python3 #coding: utf-8 Copyright (c) 2021 Huawei Device Co., Ltd. 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. Description: Generate interface to get java plugin's js code and binary # size of 8K # write method: getJsCode # write method: getJsBytecode # seperate bytecode list # generate seperate methods for js bytecode with ARRAY_MAX # generate a method collect all seperated arrays