#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2022 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.

import os
import re
from bundle_check.bundle_check_common import BundleCheckTools
from bundle_check.warning_info import BCWarnInfo


class BundleCheckOnline:
    '''用于检查 bundle.json pr。'''

    @staticmethod
    def check_diff(diff:dict):
        '''
        @func: 根据 diff 部分对 bundle.json 进行静态检查。
        @parm:
            ``diff``: 格式化后的字典类型的 diff 文件修改信息。示例:
                d = {
                    "path1/bundle.json": [
                        [line1, "content1"],
                        [line2, "content2"]
                    ]
                }
        '''
        diff_dict = {}
        for file_path in diff:
            diff_dict[file_path] = []
            diff_list = diff[file_path]
            for i in diff_list:
                if '/third_party_' in file_path and 'name' in i[1]:
                    continue
                ret = BundleCheckOnline.check_diff_by_line(i[1])
                if not ret:
                    continue
                line = list(("line" + str(i[0]) + ": " + i[1], ret))
                if file_path in diff_dict.keys():
                    diff_dict[file_path].append(line)
        # trans to list
        err_list = []
        for file in diff_dict:
            for i in diff_dict[file]:
                row = [file, i[0]]
                row.extend([BCWarnInfo.CHECK_RULE_2_1, i[1]])
                err_list.append(row)
        if err_list:
            return True, err_list
        else:
            return False, err_list

    def check_diff_by_line(line:str) -> str:
        line = line.strip()
        match = re.match(r'"(\w+)"\s*:\s*"(.*)"', line)
        if not match:
            return ""
        key = match.group(1)
        value = match.group(2)
        
        if key == 'name':
            return _check_line_name(value)
        if key == 'version':
            if len(value) == 0:
                return BCWarnInfo.VERSION_EMPTY
            else:
                return ""
        if key == 'destPath':
            if os.path.isabs(value):
                return BCWarnInfo.SEGMENT_DESTPATH_ABS
            return ""
        if key == 'subsystem':
            if not re.match(r'[a-z]+$', value):
                return BCWarnInfo.COMPONENT_SUBSYSTEM_LOWCASE
        if key == 'rom' or key == 'ram':
            return _check_line_rom_ram(key, value)
        if key == 'syscap':
            return _check_line_syscap(value)
        if key == 'features':
            if len(value) == 0:
                return BCWarnInfo.COMPONENT_FEATURES_STRING_EMPTY
        return ""


def _check_line_name(value: str):
    if not value: # value empty
        return BCWarnInfo.NAME_EMPTY
    if value.startswith('//') and ':' in value: # exclude inner_kits:name
        return ""
    if ('/' in value) and (not BundleCheckTools.match_bundle_full_name(value)):
        return BCWarnInfo.NAME_FORMAT_ERROR + \
            BCWarnInfo.COMPONENT_NAME_FROMAT_LEN

    component_name = value.split('/')[1] if ('/' in value) else value
    if not BundleCheckTools.match_unix_like_name(component_name):
        return BCWarnInfo.COMPONENT_NAME_FROMAT
    return ""


def _check_line_version(value):
    if len(value) < 3:
        return BCWarnInfo.VERSION_ERROR
    ohos_root_path = BundleCheckTools.get_root_path()
    if not ohos_root_path:
        # when project is not exist, do not raise checking error
        return ""
    ohos_version = BundleCheckTools.get_ohos_version(ohos_root_path)
    if ohos_version and value != ohos_version:
        return BCWarnInfo.VERSION_ERROR + ' ohos version is: ' + value
    return ""


def _check_line_rom_ram(key, value):
    if len(value) == 0:
        return r'"component:rom/ram" 字段不能为空。'
    num, unit = BundleCheckTools.split_by_unit(value)
    if num < 0:
        return '"component:{}" 非数值或者小于等于 0。'.format(key)
    if unit:
        unit_types = ["KB", "KByte", "MByte", "MB"]
        if unit not in unit_types:
            return '"component:{}" 的单位错误(KB, KByte, MByte, MB,默认为KByte)。'.format(key)
    return ""


def _check_line_syscap(value):
    if len(value) == 0:
        return BCWarnInfo.COMPONENT_SYSCAP_STRING_EMPTY
    match = re.match(r'^SystemCapability(\.[A-Z][a-zA-Z]{1,63}){2,6}$', value)
    if not match:
        return BCWarnInfo.COMPONENT_SYSCAP_STRING_FORMAT_ERROR
    return ""