package mara.mybox.fxml;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import mara.mybox.controller.BaseController;
import mara.mybox.controller.ColorQueryController;
import mara.mybox.controller.WebBrowserController;
import mara.mybox.data.ImageItem;
import mara.mybox.data.StringTable;
import mara.mybox.dev.MyBoxLog;
import mara.mybox.fxml.menu.MenuTools;
import mara.mybox.fxml.style.HtmlStyles;
import mara.mybox.tools.FileTmpTools;
import mara.mybox.tools.HtmlWriteTools;
import mara.mybox.tools.MarkdownTools;
import mara.mybox.tools.TextFileTools;
import static mara.mybox.value.AppValues.JavaVersion;
import mara.mybox.value.AppVariables;
import mara.mybox.value.InternalImages;
import mara.mybox.value.Languages;
import static mara.mybox.value.Languages.message;

/**
 * @Author Mara
 * @CreateDate 2022-8-8
 * @License Apache License Version 2.0
 */
public class HelpTools {

    public static void readMe(BaseController controller) {
        try {
            File htmlFile = makeReadMe(Languages.embedFileLang());
            if (htmlFile == null) {
                return;
            }
            PopTools.browseURI(controller, htmlFile.toURI());
            SoundTools.miao5();
        } catch (Exception e) {
            MyBoxLog.error(e);
        }
    }

    public static File makeReadMe(String fileLang) {
        try {
            File htmlFile = new File(AppVariables.MyboxDataPath + "/doc/readme_" + fileLang + ".html");
            File mdFile = FxFileTools.getInternalFile("/doc/" + fileLang + "/README.md",
                    "doc", "README-" + fileLang + ".md", true);
            String html = MarkdownTools.md2html(null,
                    MarkdownTools.htmlOptions(), mdFile, HtmlStyles.DefaultStyle);
            if (html == null) {
                return null;
            }
            html = html.replaceAll("href=\"", "target=_blank href=\"");
            TextFileTools.writeFile(htmlFile, html);
            return htmlFile;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutColor() {
        try {
            StringTable table = new StringTable(null, message("ResourcesAboutColor"));
            table.newLinkRow(message("ICCWebsite"), "http://www.color.org");
            table.newLinkRow(message("ICCProfileTags"), "https://sno.phy.queensu.ca/~phil/exiftool/TagNames/ICC_Profile.html");
            table.newLinkRow(message("IccProfilesECI"), "http://www.eci.org/en/downloads");
            table.newLinkRow(message("IccProfilesAdobe"), "https://supportdownloads.adobe.com/detail.jsp?ftpID=3680");
            table.newLinkRow(message("ColorSpace"), "http://brucelindbloom.com/index.html?WorkingSpaceInfo.html#Specifications");
            table.newLinkRow(message("StandardsRGB"), "https://www.w3.org/Graphics/Color/sRGB.html");
            table.newLinkRow(message("RGBXYZMatrices"), "http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html");
            table.newLinkRow(message("ColorCalculator"), "http://www.easyrgb.com/en/math.php");
            table.newLinkRow("", "http://brucelindbloom.com/index.html?ColorCalculator.html");
            table.newLinkRow("", "http://davengrace.com/cgi-bin/cspace.pl");
            table.newLinkRow(message("ColorData"), "https://www.rit.edu/science/pocs/useful-data");
            table.newLinkRow("", "http://www.thefullwiki.org/Standard_illuminant");
            table.newLinkRow(message("ColorTopics"), "https://www.codeproject.com/Articles/1202772/Color-Topics-for-Programmers");
            table.newLinkRow("", "https://www.w3.org/TR/css-color-4/#lab-to-rgb");
            table.newLinkRow(message("ChromaticAdaptation"), "http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html");
            table.newLinkRow(message("ChromaticityDiagram"), "http://demonstrations.wolfram.com/CIEChromaticityDiagram/");
            table.newLinkRow(message("ArtHuesWheel"), "https://blog.csdn.net/weixin_44938037/article/details/90599711");
            table.newLinkRow("", "https://stackoverflow.com/questions/4945457/conversion-between-rgb-and-ryb-color-spaces");
            table.newLinkRow("", "https://math.stackexchange.com/questions/305395/ryb-and-rgb-color-space-conversion");
            table.newLinkRow("", "http://bahamas10.github.io/ryb/about.html");
            table.newLinkRow("", "https://redyellowblue.org/ryb-color-model/");

            File htmFile = HtmlWriteTools.writeHtml(table.html());
            return htmFile;

        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutDataAnalysis() {
        try {
            StringTable table = new StringTable(null, message("AboutDataAnalysis"));
            table.newLinkRow(message("Dataset"), "http://archive.ics.uci.edu/ml/datasets.php");
            table.newLinkRow("", "https://www4.stat.ncsu.edu/~boos/var.select/");
            table.newLinkRow("", "http://lib.stat.cmu.edu/datasets/");
            table.newLinkRow("", "http://yann.lecun.com/exdb/mnist/");
            table.newLinkRow("", "https://docs.microsoft.com/en-us/azure/open-datasets/");
            table.newLinkRow("", "https://github.com/tomsharp/SVR/tree/master/data");
            table.newLinkRow("", "https://github.com/krishnaik06/simple-Linear-Regression");
            table.newLinkRow("", "https://github.com/susanli2016/Machine-Learning-with-Python/tree/master/data");
            table.newLinkRow("", "https://www.datarepository.movebank.org");
            table.newLinkRow("", "https://github.com/CSSEGISandData/COVID-19");
            table.newLinkRow("", "https://data.stats.gov.cn/index.htm");
            table.newLinkRow("Apache-Math", "https://commons.apache.org/proper/commons-math/");
            table.newLinkRow("", "https://commons.apache.org/proper/commons-math/apidocs/index.html");
            table.newLinkRow(message("Study"), "https://github.com/InfolabAI/DeepLearning");
            table.newLinkRow("", "https://www.deeplearningbook.org/");
            table.newLinkRow("", "https://github.com/zsdonghao/deep-learning-book");
            table.newLinkRow("", "https://github.com/hadrienj/deepLearningBook-Notes");
            table.newLinkRow("", "https://github.com/janishar/mit-deep-learning-book-pdf");
            table.newLinkRow("", "https://clauswilke.com/dataviz/");
            table.newLinkRow("", "https://www.kancloud.cn/apachecn/dataviz-zh/1944809");
            table.newLinkRow("", "https://www.bilibili.com/video/BV1Ua4y1e7YG");
            table.newLinkRow("", "https://www.bilibili.com/video/BV1i7411d7aP");
            table.newLinkRow("", "https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes");
            table.newLinkRow(message("Tools"), "https://scikit-learn.org/stable/");
            table.newLinkRow("", "https://www.mathworks.com/help/index.html");
            table.newLinkRow(message("Example"), "https://www.xycoon.com/simple_linear_regression.htm");
            table.newLinkRow("", "https://www.scribbr.com/statistics/simple-linear-regression/");
            table.newLinkRow("", "http://www.datasetsanalysis.com/regressions/simple-linear-regression.html");

            File htmFile = HtmlWriteTools.writeHtml(table.html());
            return htmFile;

        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutCoordinateSystem() {
        try {
            StringTable table = new StringTable(null, message("AboutCoordinateSystem"));
            table.newLinkRow(message("ChinaCommonGeospatialInformationServices"), "https://www.tianditu.gov.cn/");
            table.newLinkRow("", "https://www.tianditu.gov.cn/world_coronavirusmap/");
            table.newLinkRow(message("ChineseCoordinateSystems"), "https://politics.stackexchange.com/questions/40991/why-must-chinese-maps-be-obfuscated");
            table.newLinkRow("", "https://zhuanlan.zhihu.com/p/62243160");
            table.newLinkRow("", "https://blog.csdn.net/qq_36377037/article/details/86479796");
            table.newLinkRow("", "https://www.zhihu.com/question/31204062?sort=created");
            table.newLinkRow("", "https://blog.csdn.net/ssxueyi/article/details/102622156");
            table.newLinkRow(message("EPSGCodes"), "http://epsg.io/4490");
            table.newLinkRow("", "http://epsg.io/4479");
            table.newLinkRow("", "http://epsg.io/4326");
            table.newLinkRow("", "http://epsg.io/3857");
            table.newLinkRow(message("TrackingData"), "https://www.microsoft.com/en-us/download/details.aspx?id=52367");
            table.newLinkRow("", "https://www.datarepository.movebank.org/discover");
            table.newLinkRow("", "https://sumo.dlr.de/docs/Data/Scenarios/TAPASCologne.html");
            table.newLinkRow("", "https://blog.csdn.net/souvenir001/article/details/52180335");
            table.newLinkRow("", "https://www.cnblogs.com/genghenggao/p/9625511.html");
            table.newLinkRow(message("TianDiTuAPI"), "http://lbs.tianditu.gov.cn/api/js4.0/guide.html");
            table.newLinkRow(message("TianDiTuKey"), "https://console.tianditu.gov.cn/api/key");
            table.newLinkRow(message("GaoDeAPI"), "https://lbs.amap.com/api/javascript-api/summary");
            table.newLinkRow(message("GaoDeKey"), "https://console.amap.com/dev/index");
            File htmFile = HtmlWriteTools.writeHtml(table.html());
            return htmFile;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutMedia() {
        try {
            StringTable table = new StringTable(null, message("AboutMedia"));
            table.newLinkRow(message("FFmpegDocuments"), "http://ffmpeg.org/documentation.html");
            table.newLinkRow(message("FFmpeg wiki"), "https://trac.ffmpeg.org");
            table.newLinkRow(message("H264VideoEncodingGuide"), "http://trac.ffmpeg.org/wiki/Encode/H.264");
            table.newLinkRow(message("AACEncodingGuide"), "https://trac.ffmpeg.org/wiki/Encode/AAC");
            table.newLinkRow(message("UnderstandingRateControlModes"), "https://slhck.info/video/2017/03/01/rate-control.html");
            table.newLinkRow(message("CRFGuide"), "https://slhck.info/video/2017/02/24/crf-guide.html");
            table.newLinkRow(message("CapturingDesktopScreenRecording"), "http://trac.ffmpeg.org/wiki/Capture/Desktop");

            File htmFile = HtmlWriteTools.writeHtml(table.html());
            return htmFile;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutMacro() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_macro_" + lang + ".html",
                    "doc", "mybox_about_macro_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutData2D() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_data2d_" + lang + ".html",
                    "doc", "mybox_about_data2d_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutGroupingRows() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_grouping_" + lang + ".html",
                    "doc", "mybox_about_grouping_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutRowExpression() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_row_expression_" + lang + ".html",
                    "doc", "mybox_about_row_expression_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutTreeInformation() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_tree_" + lang + ".html",
                    "doc", "mybox_about_tree_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File aboutImageScope() {
        try {
            String lang = Languages.embedFileLang();
            File file = FxFileTools.getInternalFile("/doc/" + lang + "/mybox_about_image_scope_" + lang + ".html",
                    "doc", "mybox_about_image_scope_" + lang + ".html");
            return file;
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static void imageStories(BaseController controller) {
        FxTask task = new FxTask<Void>(controller) {
            private File htmFile;

            @Override
            protected boolean handle() {
                htmFile = imageStories(this, false, AppVariables.CurrentLangName);
                return htmFile != null && htmFile.exists();
            }

            @Override
            protected void whenSucceeded() {
                controller.browse(htmFile);
            }

        };
        controller.start(task);
    }

    public static File imageStories(FxTask task, boolean isRemote, String lang) {
        try {
            StringTable table = new StringTable(null, message(lang, "StoriesOfImages"));
            List<ImageItem> imageItems = InternalImages.all(lang);
            for (ImageItem item : imageItems) {
                String comments = item.getComments();
                File file = item.getFile();
                if (comments == null || comments.isBlank()
                        || file == null || !file.exists()) {
                    continue;
                }
                task.setInfo(file.getAbsolutePath());
                table.newNameValueRow(
                        "<Img src='" + (isRemote
                                ? "https://mara-mybox.sourceforge.io/images/" + file.getName()
                                : file.toURI().toString())
                        + "' width=" + item.getWidth() + ">",
                        comments);
            }

            String html = HtmlWriteTools.html(table.getTitle(), "utf-8",
                    HtmlStyles.styleValue("Table"), table.body());
            File file = new File(FileTmpTools.generatePath("html")
                    + "/MyBox-StoriesOfImages-" + lang + ".html");
            return TextFileTools.writeFile(file, html);

        } catch (Exception e) {
            task.setError(e.toString());
            return null;
        }
    }

    public static File usefulLinks(String lang) {
        try {
            StringTable table = new StringTable(null, message(lang, "Links"));
            table.newLinkRow(message(lang, "DecimalFormat"), decimalFormatLink());
            table.newLinkRow(message(lang, "DateFormat"), simpleDateFormatLink());
            table.newLinkRow(message(lang, "Charset"), charsetLink());
            table.newLinkRow(message(lang, "Color"), colorLink());
            table.newLinkRow("URI", uriLink());
            table.newLinkRow("URL", urlLink());
            table.newLinkRow("Full list of Math functions", javaMathLink());
            table.newLinkRow("Learning the Java Language", javaLink());
            table.newLinkRow("Java Development Kit (JDK) APIs", javaAPILink());
            table.newLinkRow(message(lang, "JavafxCssGuide"), javaFxCssLink());
            table.newLinkRow(message(lang, "DerbyReferenceManual"), derbyLink());
            table.newLinkRow(message(lang, "SqlIdentifier"), sqlLink());
            table.newLinkRow(message(lang, "HtmlTutorial") + " - " + message(lang, "Chinese"), htmlZhLink());
            table.newLinkRow(message(lang, "HtmlTutorial") + " - " + message(lang, "English"), htmlEnLink());
            table.newLinkRow(message(lang, "JavaScriptTutorial") + " - " + message(lang, "Chinese"), javaScriptZhLink());
            table.newLinkRow(message(lang, "JavaScriptTutorial") + " - " + message(lang, "English"), javaScriptEnLink());
            table.newLinkRow("JavaScript language specification", javaScriptSpecification());
            table.newLinkRow("Nashorn User's Guide", nashornLink());
            table.newLinkRow(message(lang, "CssTutorial") + " - " + message(lang, "Chinese"), cssZhLink());
            table.newLinkRow(message(lang, "CssTutorial") + " - " + message(lang, "English"), cssEnLink());
            table.newLinkRow(message(lang, "CssReference"), cssSpecificationLink());
            table.newLinkRow("RenderingHints", renderingHintsLink());
            table.newLinkRow(message(lang, "JsonTutorial") + " - " + message(lang, "Chinese"), jsonZhLink());
            table.newLinkRow(message(lang, "JsonTutorial") + " - " + message(lang, "English"), jsonEnLink());
            table.newLinkRow(message(lang, "JsonSpecification"), jsonSpecification());
            table.newLinkRow(message(lang, "XmlTutorial") + " - " + message(lang, "Chinese"), xmlZhLink());
            table.newLinkRow(message(lang, "XmlTutorial") + " - " + message(lang, "English"), xmlEnLink());
            table.newLinkRow(message(lang, "DomSpecification"), domSpecification());
            table.newLinkRow(message(lang, "SvgTutorial") + " - " + message(lang, "Chinese"), svgZhLink());
            table.newLinkRow(message(lang, "SvgTutorial") + " - " + message(lang, "English"), svgEnLink());
            table.newLinkRow(message(lang, "SvgSpecification"), svgSpecification());
            table.newLinkRow("SVGPath in JavaFX", javafxSVGPathLink());
            table.newLinkRow("Shape 2D in JavaFX", javafxShape2DLink());
            table.newLinkRow("Shape 2D in Java", javaShape2DLink());

            String html = HtmlWriteTools.html(message(lang, "Links"), HtmlStyles.DefaultStyle, table.div());

            File file = new File(FileTmpTools.generatePath("html")
                    + "/mybox_useful_link_" + lang + ".html");

            return TextFileTools.writeFile(file, html);
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    public static File makeInterfaceTips(String lang) {
        try {
            StringBuilder s = new StringBuilder();
            s.append("<BODY>\n");

            s.append("<H1>").append(message(lang, "DocumentTools")).append("</H1>\n");

            s.append("    <H3>").append(message(lang, "PdfView")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "PdfViewTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "MarkdownEditer")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MarkdownEditerTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "HtmlEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "HtmlFormatTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "HtmlSnap")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "HtmlSnapComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "JsonEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "JsonEditorTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "XmlEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "XmlEditorTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "TextEditer")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "TextEditerTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "Charset")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "EncodeComments"))).append("\n");

            s.append("    <H3>").append("BOM").append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "BOMcomments"))).append("\n");

            s.append("    <H3>").append(message(lang, "FindReplace")).append(" - ").append(message(lang, "Texts")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "FindReplaceTextsTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "FindReplace")).append(" - ").append(message(lang, "Bytes")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "FindReplaceBytesTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "FilterLines")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "FilterTypesComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "TextFindBatch")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "TextFindBatchTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "TextReplaceBatch")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "TextReplaceBatchTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "TextToHtml")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "PasteTextAsHtml"))).append("\n");

            s.append("    <H3>").append(message(lang, "BytesFindBatch")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "BytesFindBatchTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "TextInMyBoxClipboard")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "TextClipboardUseComments"))).append("</BR>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "TextInMyBoxClipboardTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "WordView")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "WordViewTips"))).append("\n");

            s.append("\n");

            s.append("<H1>").append(message(lang, "ImageTools")).append("</H1>\n");

            s.append("    <H3>").append(message(lang, "EditImage")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageEditTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "SVGEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SVGEditorTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageQuantization")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageQuantizationComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "Dithering")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DitherComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "ColorMatching")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ColorMatchComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "PremultipliedAlpha")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "PremultipliedAlphaTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "Thresholding")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageThresholdingComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "Contrast")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageContrastComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "Shear")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageShearComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageRepeatTile")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageRepeatTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageSample")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageSampleTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageSplit")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageSplitTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImagesEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImagesEditorTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImagesPlay")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImagesPlayTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageOCR")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageOCRComments"))).append("</BR>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "OCRPreprocessComment"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageAlphaExtract")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ImageAlphaExtractTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImageToSvg")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SvgFromImageComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "ImagesInSystemClipboard")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "RecordImagesTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ManageColors")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ColorsManageTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "DrawChromaticityDiagram")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ChromaticityDiagramTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "IccProfileEditor")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "IccProfileTips"))).append("\n");

            s.append("\n");

            s.append("<H1>").append(message(lang, "NetworkTools")).append("</H1>\n");
            s.append("    <H3>").append(message(lang, "DownloadHtmls")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DownloadFirstLevelLinksComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "ConvertUrl")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ConvertUrlTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "QueryDNSBatch")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "QueryDNSBatchTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "WeiboSnap")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "WeiboAddressComments"))).append("\n");

            s.append("\n");

            s.append("<H1>").append(message(lang, "DataTools")).append("</H1>\n");

            s.append("    <H3>").append(message(lang, "Column")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ColumnComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "ManageData")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DataManageTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "DatabaseTable")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DataTableTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "SqlIdentifier")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SqlIdentifierComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "XYChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DataChartXYTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "PieChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "DataChartPieTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "BoxWhiskerChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "BoxWhiskerChartTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "ComparisonBarsChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "ComparisonBarsChartTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "SelfComparisonBarsChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SelfComparisonBarsChartTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "XYZChart")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "WebglComments"))).append("\n");

            s.append("    <H3>").append(message(lang, "SetStyles")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SetStylesTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "SimpleLinearRegression")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SimpleLinearRegressionTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "SimpleLinearRegressionCombination")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "SimpleLinearRegressionCombinationTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "MultipleLinearRegression")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MultipleLinearRegressionTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "MultipleLinearRegressionCombination")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MultipleLinearRegressionCombinationTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "Matrix")).append("</H3>\n");

            s.append("    <H4>").append(message(lang, "Plus")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MatricesPlusComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "Minus")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MatricesMinusComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "Multiply")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "MatricesMultiplyComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "HadamardProduct")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "HadamardProductComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "KroneckerProduct")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "KroneckerProductComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "VerticalMerge")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "VerticalMergeComments"))).append("\n");

            s.append("    <H4>").append(message(lang, "HorizontalMerge")).append("</H4>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "HorizontalMergeComments"))).append("\n");

            s.append("\n");

            s.append("    <H3>").append(message(lang, "JavaScript")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "JavaScriptTips"))).append("\n");

            s.append("    <H3>").append(message(lang, "JShell")).append("</H3>\n");
            s.append(HtmlWriteTools.codeToHtml(message(lang, "JShellTips"))).append("\n");

