1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import ExcelJS from 'exceljs';
17import path from 'path';
18import fs from 'fs';
19import { LogUtil } from '../utils/logUtil';
20import { ToolNameExcelCallback, joinNewMessage, joinOldMessage, ToolReturnData } from './config';
21import { BasicDiffInfo, diffTypeMap } from '../typedef/diff/ApiInfoDiff';
22import { OptionObjType } from './config';
23import { SyscapProcessorHelper } from '../coreImpl/diff/syscapFieldProcessor';
24
25export namespace WriterHelper {
26  export function JSONReporter(data: string, dest: string, fileName: string) {
27    const outputFile = path.resolve(dest, fileName);
28    fs.writeFileSync(outputFile, data);
29    LogUtil.i('JSONReporter', `report is in ${outputFile}`);
30  }
31
32  export async function ExcelReporter(
33    data: ToolReturnData,
34    dest: string,
35    fileName: string,
36    callback: ToolNameExcelCallback | undefined,
37    options?: OptionObjType
38  ) {
39    const workbook: ExcelJS.Workbook = new ExcelJS.Workbook();
40    if (typeof callback === 'function') {
41      //callback是一个函数,才能当回调函数使用
42      callback(data, workbook, dest, options);
43    }
44
45    const buffer: NodeJS.ArrayBufferView = (await workbook.xlsx.writeBuffer()) as NodeJS.ArrayBufferView;
46    const outputFile: string = path.resolve(dest, fileName);
47    fs.writeFileSync(outputFile, buffer);
48    LogUtil.i('ExcelReporter', `report is in ${outputFile}`);
49  }
50
51  export class MarkdownReporter {
52    static writeInMarkdown(data: BasicDiffInfo[], dest: string | undefined): void {
53      const kitInfoSet: Set<string> = MarkdownReporter.getAllKitInfo(data);
54      kitInfoSet.forEach((kitInfo: string) => {
55        let diffsInSameKit: BasicDiffInfo[] = [];
56        data.forEach((diffInfo: BasicDiffInfo) => {
57          if (SyscapProcessorHelper.getSingleKitInfo(diffInfo) === kitInfo) {
58            diffsInSameKit.push(diffInfo);
59          }
60        });
61
62        if (diffsInSameKit.length === 0) {
63          return;
64        }
65
66        MarkdownReporter.sortDiffInfoByFile(diffsInSameKit, kitInfo, dest);
67      });
68    }
69
70    /**
71     * 获取所有的kit信息
72     *
73     * @param {BasicDiffInfo[]} data
74     * @returns
75     */
76    static getAllKitInfo(data: BasicDiffInfo[]): Set<string> {
77      const kitInfoSet: Set<string> = new Set();
78      data.forEach((diffInfo) => {
79        kitInfoSet.add(diffInfo.getOldKitInfo());
80        kitInfoSet.add(diffInfo.getNewKitInfo());
81      });
82      return kitInfoSet;
83    }
84
85    static getSingleKitInfo(data: BasicDiffInfo): string {
86      if (data.getNewKitInfo() !== '') {
87        return data.getNewKitInfo();
88      }
89      return data.getOldKitInfo();
90    }
91
92    static getFileNameInkit(diffsInSameSystem: BasicDiffInfo[]): Set<string> {
93      const fileNameSet: Set<string> = new Set();
94      diffsInSameSystem.forEach((diffInfo) => {
95        if (diffInfo.getNewDtsName() !== '') {
96          fileNameSet.add(diffInfo.getNewDtsName());
97        } else {
98          fileNameSet.add(diffInfo.getOldDtsName());
99        }
100      });
101      return fileNameSet;
102    }
103
104    static getSingleFileName(data: BasicDiffInfo): string {
105      if (data.getNewDtsName() !== '') {
106        return data.getNewDtsName();
107      }
108      return data.getOldDtsName();
109    }
110
111    /**
112     * 使用文件名进行排序
113     *
114     * @param { BasicDiffInfo[] } diffsInSameKit 所属kit一样的diffInfo
115     * @param { string } kitInfo kit信息
116     * @param dest
117     */
118    static sortDiffInfoByFile(diffsInSameKit: BasicDiffInfo[], kitInfo: string, dest: string | undefined): void {
119      const fileNameSet = MarkdownReporter.getFileNameInkit(diffsInSameKit);
120      const diffInfosInSameFile: BasicDiffInfo[] = [];
121      fileNameSet.forEach((fileName: string) => {
122        diffsInSameKit.forEach((diffInfo: BasicDiffInfo) => {
123          if (MarkdownReporter.getSingleFileName(diffInfo) === fileName) {
124            diffInfosInSameFile.push(diffInfo);
125          }
126        });
127        MarkdownReporter.sortDiffInfoByStatus(diffInfosInSameFile, kitInfo, dest);
128      });
129    }
130
131    static sortDiffInfoByStatus(diffsInSameSystem: BasicDiffInfo[], kitInfo: string, dest: string | undefined): void {
132      const sortDiffInfos: BasicDiffInfo[] = [];
133      for (const type of diffTypeMap.keys()) {
134        diffsInSameSystem.forEach((diffInfo) => {
135          if (diffInfo.getDiffType() === type) {
136            sortDiffInfos.push(diffInfo);
137          }
138        });
139      }
140      MarkdownReporter.exportDiffMd(kitInfo, sortDiffInfos, dest);
141    }
142
143    static exportDiffMd(kitInfo: string, diffInfos: BasicDiffInfo[], dest: string | undefined): void {
144      let markDownContent: string =
145        '| 操作 | 旧版本 | 新版本 | d.ts文件 |\n' + '| ---- | ------ | ------ | -------- |\n';
146      for (let i = 0; i < diffInfos.length; i++) {
147        let diffInfo: BasicDiffInfo = diffInfos[i];
148        const dtsName = diffInfo.getNewDtsName() ? diffInfo.getNewDtsName() : diffInfo.getOldDtsName();
149        markDownContent +=
150          `|${diffTypeMap.get(diffInfo.getDiffType())}|${MarkdownReporter.formatDiffMessage(
151            joinOldMessage(diffInfo)
152          )}` + `|${MarkdownReporter.formatDiffMessage(joinNewMessage(diffInfo))}|${dtsName.replace(/\\/g, '/')}|\n`;
153      }
154      const mdFilesDir = `${dest}\\diff合集`;
155      if (!fs.existsSync(mdFilesDir)) {
156        fs.mkdirSync(mdFilesDir);
157      }
158
159      fs.writeFileSync(`${dest}\\diff合集\\js-apidiff-${kitInfo}.md`, markDownContent);
160    }
161
162    static formatDiffMessage(diffMessage: string): string {
163      const message = diffMessage
164        .replace(/\r|\n/g, '<br>')
165        .replace(/\|/g, '\\|')
166        .replace(/\<(?!br>)/g, '\\<');
167      return message;
168    }
169  }
170}
171