//
//  StringsFileGeneratorTests.swift
//
//
//  Created by Thibaut Schmitt on 06/09/2022.
//

import Foundation
import XCTest
import ToolCore

@testable import ResgenSwift

final class StringsFileGeneratorTests: XCTestCase {

    private func getDefinition(name: String, translations: [String: String], tags: [String], comment: String? = nil) -> Definition {
        let definition = Definition(name: name)
        definition.tags = tags
        definition.translations = translations
        definition.comment = comment
        return definition
    }

    // MARK: - Strings File Content

    func testGenerateStringsFileContent() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"])
        ]

        // When
        let stringsFileContentFr = StringsFileGenerator.generateStringsFileContent(lang: "fr",
                                                                                   defaultLang: "fr",
                                                                                   tags: ["ios", "iosonly", "notranslation"],
                                                                                   sections: [sectionOne, sectionTwo])
        let stringsFileContentEn = StringsFileGenerator.generateStringsFileContent(lang: "en",
                                                                                   defaultLang: "fr",
                                                                                   tags: ["ios", "iosonly", "notranslation"],
                                                                                   sections: [sectionOne, sectionTwo])

        // Expect
        let expectFr = """
        /**
         * Apple Strings File
         * Generated by ResgenSwift \(ResgenSwiftVersion)
         * Language: fr
         */

        /********** section_one **********/

        "s1_def_one" = "Section Un - Definition Un";

        "s1_def_two" = "Section Un - Definition Deux";

        /********** section_two **********/

        "s2_def_one" = "Section Deux - Definition Un";

        "s2_def_two" = "Section Deux - Definition Deux";
        """

        let expectEn = """
        /**
         * Apple Strings File
         * Generated by ResgenSwift \(ResgenSwiftVersion)
         * Language: en
         */

        /********** section_one **********/

        "s1_def_one" = "Section One - Definition One";

        "s1_def_two" = "Section One - Definition Two";

        /********** section_two **********/

        "s2_def_one" = "Section Two - Definition One";

        "s2_def_two" = "Section Deux - Definition Deux";
        """

        XCTAssertEqual(stringsFileContentFr.adaptForXCTest(), expectFr.adaptForXCTest())
        XCTAssertEqual(stringsFileContentEn.adaptForXCTest(), expectEn.adaptForXCTest())
    }

    func testGenerateStringsFileContentWithComment() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment")
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"],
                          comment: "This is a comment")
        ]

        // When
        let stringsFileContentFr = StringsFileGenerator.generateStringsFileContent(lang: "fr",
                                                                                   defaultLang: "fr",
                                                                                   tags: ["ios", "iosonly", "notranslation"],
                                                                                   sections: [sectionOne, sectionTwo])
        let stringsFileContentEn = StringsFileGenerator.generateStringsFileContent(lang: "en",
                                                                                   defaultLang: "fr",
                                                                                   tags: ["ios", "iosonly", "notranslation"],
                                                                                   sections: [sectionOne, sectionTwo])

        // Expect
        let expectFr = """
        /**
         * Apple Strings File
         * Generated by ResgenSwift \(ResgenSwiftVersion)
         * Language: fr
         */

        /********** section_one **********/

        "s1_def_one" = "Section Un - Definition Un";

        "s1_def_two" = "Section Un - Definition Deux";

        /********** section_two **********/

        "s2_def_one" = "Section Deux - Definition Un";

        "s2_def_two" = "Section Deux - Definition Deux";
        """

        let expectEn = """
        /**
         * Apple Strings File
         * Generated by ResgenSwift \(ResgenSwiftVersion)
         * Language: en
         */

        /********** section_one **********/

        "s1_def_one" = "Section One - Definition One";

        "s1_def_two" = "Section One - Definition Two";

        /********** section_two **********/

        "s2_def_one" = "Section Two - Definition One";

        "s2_def_two" = "Section Deux - Definition Deux";
        """

        XCTAssertEqual(stringsFileContentFr.adaptForXCTest(), expectFr.adaptForXCTest())
        XCTAssertEqual(stringsFileContentEn.adaptForXCTest(), expectEn.adaptForXCTest())
    }

    // MARK: - XcString File Content

    func testGenerateXcStringsRootObject() {
        // Given

        //        [[section_one]]
        //            [s1_def_one]
        //                fr = Section Un - Definition Un
        //                en = Section One - Definition One
        //                tags = ios,iosonly
        //                comments =
        //            [s1_def_two]
        //                fr = Section Un - Definition Deux
        //                en = Section One - Definition Two
        //                tags = ios,iosonly
        //                comments =
        //
        //        [[section_two]
        //            [s2_def_one]
        //                fr = Section Deux - Definition Un
        //                en = Section Two - Definition One
        //                tags = ios,iosonly
        //                comments =
        //            [s2_def_two]
        //                fr = Section Deux - Definition deux
        //                en = Section Two - Definition Two
        //                tags = notranslation
        //                comments =


        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux",
                                         "en": "Section Two - Definition Two"],
                          tags: ["notranslation"])
        ]

        // When
        let rootObject = StringsFileGenerator.generateRootObject(
            langs: ["fr", "en"],
            defaultLang: "en",
            tags: ["ios", "iosonly", "notranslation"],
            sections: [sectionOne, sectionTwo]
        )

        // Expect
        let expect =
        Root(
            sourceLanguage: "en",
            strings: XCStringDefinitionContainer(
                strings: [
                    XCStringDefinition(
                        title: "s1_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition One"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Un - Definition Un"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s1_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition Two"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Un - Definition Deux"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition One"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Deux - Definition Un"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition Two"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition Two"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    )
                ]
            ),
            version: "1.0"
        )

        XCTAssertEqual(rootObject, expect)
    }

    func testGenerateXcStringsRootObjectWithEmptyTranslations() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["en": "Section Two - Definition Two"],
                          tags: ["notranslation"])
        ]

        // When
        let rootObject = StringsFileGenerator.generateRootObject(
            langs: ["fr", "en"],
            defaultLang: "en",
            tags: ["ios", "iosonly", "notranslation"],
            sections: [sectionOne, sectionTwo]
        )

        //        [[section_one]]
        //            [s1_def_one]
        //                fr =
        //                en = Section One - Definition One
        //                tags = ios,iosonly
        //                comments =
        //            [s1_def_two]
        //                fr =
        //                en = Section One - Definition Two
        //                tags = ios,iosonly
        //                comments =
        //
        //        [[section_two]
        //            [s2_def_one]
        //                fr =
        //                en = Section Two - Definition One
        //                tags = ios,iosonly
        //                comments =
        //            [s2_def_two]
        //                en = Section Two - Definition Two
        //                tags = notranslation
        //                comments =

        // Expect
        let expect =
        Root(
            sourceLanguage: "en",
            strings: XCStringDefinitionContainer(
                strings: [
                    XCStringDefinition(
                        title: "s1_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition One"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s1_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition Two"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition One"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition Two"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition Two"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    )
                ]
            ),
            version: "1.0"
        )

        XCTAssertEqual(rootObject, expect)
    }

    func testGenerateXcStringsRootObjectWithNoTranslations() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "",
                                         "en": ""],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "",
                                         "en": ""],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "",
                                         "en": ""],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "",
                                         "en": ""],
                          tags: ["notranslation"])
        ]

        // When
        let rootObject = StringsFileGenerator.generateRootObject(
            langs: ["fr", "en"],
            defaultLang: "en",
            tags: ["ios", "iosonly", "notranslation"],
            sections: [sectionOne, sectionTwo]
        )

        //        [[section_one]]
        //            [s1_def_one]
        //                fr =
        //                en =
        //                tags = ios,iosonly
        //                comments =
        //            [s1_def_two]
        //                fr =
        //                en =
        //                tags = ios,iosonly
        //                comments =
        //
        //        [[section_two]
        //            [s2_def_one]
        //                fr =
        //                en =
        //                tags = ios,iosonly
        //                comments =
        //            [s2_def_two]
        //                fr =
        //                en =
        //                tags = ios,iosonly
        //                comments =

        // Expect
        let expect =
        Root(
            sourceLanguage: "en",
            strings: XCStringDefinitionContainer(
                strings: [
                    XCStringDefinition(
                        title: "s1_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: []
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s1_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: []
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: []
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: []
                            )
                        )
                    )
                ]
            ),
            version: "1.0"
        )

        XCTAssertEqual(rootObject, expect)
    }

    func testGenerateXcStringsRootObjectWithComments() {
        // Given

        //        [[section_one]]
        //            [s1_def_one]
        //                fr = Section Un - Definition Un
        //                en = Section One - Definition One
        //                tags = ios,iosonly
        //                comments = Comment 1
        //            [s1_def_two]
        //                fr = Section Un - Definition Deux
        //                en = Section One - Definition Two
        //                tags = ios,iosonly
        //                comments = Comment 2
        //
        //        [[section_two]
        //            [s2_def_one]
        //                fr = Section Deux - Definition Un
        //                en = Section Two - Definition One
        //                tags = ios,iosonly
        //                comments =
        //            [s2_def_two]
        //                fr = Section Deux - Definition deux
        //                en = Section Two - Definition Two
        //                tags = notranslation
        //                comments =


        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "Comment 1"),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"],
                          comment: "Comment 2")
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"])
        ]

        // When
        let rootObject = StringsFileGenerator.generateRootObject(
            langs: ["fr", "en"],
            defaultLang: "fr",
            tags: ["ios", "iosonly", "notranslation"],
            sections: [sectionOne, sectionTwo]
        )

        // Expect
        let expect =
        Root(
            sourceLanguage: "fr",
            strings: XCStringDefinitionContainer(
                strings: [
                    XCStringDefinition(
                        title: "s1_def_one",
                        content: XCStringDefinitionContent(
                            comment: "Comment 1",
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition One"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Un - Definition Un"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s1_def_two",
                        content: XCStringDefinitionContent(
                            comment: "Comment 2",
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section One - Definition Two"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Un - Definition Deux"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_one",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Two - Definition One"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Deux - Definition Un"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    ),
                    XCStringDefinition(
                        title: "s2_def_two",
                        content: XCStringDefinitionContent(
                            extractionState: "manual",
                            localizations: XCStringLocalizationContainer(
                                localizations: [
                                    XCStringLocalization(
                                        lang: "en",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Deux - Definition Deux"
                                            )
                                        )
                                    ),
                                    XCStringLocalization(
                                        lang: "fr",
                                        content: XCStringLocalizationLangContent(
                                            stringUnit: DefaultStringUnit(
                                                state: "translated",
                                                value: "Section Deux - Definition Deux"
                                            )
                                        )
                                    )
                                ]
                            )
                        )
                    )
                ]
            ),
            version: "1.0"
        )

        //        """
        //        {
        //          "sourceLanguage" : "en",
        //          "strings" : {
        //            "s1_def_one" : {
        //              "extractionState" : "manual",
        //              "localizations" : {
        //                "en" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section One - Definition One"
        //                  }
        //                },
        //                "fr" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Un - Definition Un"
        //                  }
        //                }
        //              }
        //            },
        //            "s1_def_two" : {
        //              "extractionState" : "manual",
        //              "localizations" : {
        //                "en" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section One - Definition Two"
        //                  }
        //                },
        //                "fr" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Un - Definition Deux"
        //                  }
        //                }
        //              }
        //            },
        //            "s2_def_one" : {
        //              "extractionState" : "manual",
        //              "localizations" : {
        //                "en" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Two - Definition One"
        //                  }
        //                },
        //                "fr" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Deux - Definition Une"
        //                  }
        //                }
        //              }
        //            },
        //            "s2_def_two" : {
        //              "extractionState" : "manual",
        //              "localizations" : {
        //                "en" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Two - Definition Two"
        //                  }
        //                },
        //                "fr" : {
        //                  "stringUnit" : {
        //                    "state" : "translated",
        //                    "value" : "Section Deux - Definition Deux"
        //                  }
        //                }
        //              }
        //            }
        //          },
        //          "version" : "1.0"
        //        }
        //        """
        XCTAssertEqual(rootObject, expect)
    }

    // MARK: - Extension Content
    func testGeneratedExtensionContent() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"])
        ]

        // When
        let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo],
                                                                        defaultLang: "fr",
                                                                        tags: ["ios", "iosonly", "notranslation"],
                                                                        staticVar: false,
                                                                        inputFilename: "myInputFilename",
                                                                        extensionName: "GenStrings",
                                                                        extensionSuffix: "strings")

        // Expect
        let expect = """
        // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion)

        import UIKit

        fileprivate let kStringsFileName = "myInputFilename"

        extension GenStrings {

            enum KeyStrings: String {
                case s1_def_one = "s1_def_one"
                case s1_def_two = "s1_def_two"
                case s2_def_one = "s2_def_one"
                case s2_def_two = "s2_def_two"

                var keyPath: KeyPath<GenStrings, String> {
                    switch self {
                    case .s1_def_one: return \\GenStrings.s1_def_one
                    case .s1_def_two: return \\GenStrings.s1_def_two
                    case .s2_def_one: return \\GenStrings.s2_def_one
                    case .s2_def_two: return \\GenStrings.s2_def_two
                    }
                }
            }

            // MARK: - section_one

            /// Translation in fr :
            /// Section Un - Definition Un
            ///
            /// Comment :
            /// No comment
            var s1_def_one: String {
                NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "")
            }

            /// Translation in fr :
            /// Section Un - Definition Deux
            ///
            /// Comment :
            /// No comment
            var s1_def_two: String {
                NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "")
            }

            // MARK: - section_two

            /// Translation in fr :
            /// Section Deux - Definition Un
            ///
            /// Comment :
            /// No comment
            var s2_def_one: String {
                NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "")
            }

            /// Translation in fr :
            /// Section Deux - Definition Deux
            ///
            /// Comment :
            /// No comment
            var s2_def_two: String {
                NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "")
            }
        }
        """

        if extensionContent != expect {
            print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
        }
        XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
    }

    func testGeneratedExtensionContentWithComment() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment")
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"],
                          comment: "This is a comment")
        ]

        // When
        let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo],
                                                                        defaultLang: "fr",
                                                                        tags: ["ios", "iosonly", "notranslation"],
                                                                        staticVar: false,
                                                                        inputFilename: "myInputFilename",
                                                                        extensionName: "GenStrings",
                                                                        extensionSuffix: "strings")

        // Expect
        let expect = """
        // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion)

        import UIKit

        fileprivate let kStringsFileName = "myInputFilename"

        extension GenStrings {

            enum KeyStrings: String {
                case s1_def_one = "s1_def_one"
                case s1_def_two = "s1_def_two"
                case s2_def_one = "s2_def_one"
                case s2_def_two = "s2_def_two"

                var keyPath: KeyPath<GenStrings, String> {
                    switch self {
                    case .s1_def_one: return \\GenStrings.s1_def_one
                    case .s1_def_two: return \\GenStrings.s1_def_two
                    case .s2_def_one: return \\GenStrings.s2_def_one
                    case .s2_def_two: return \\GenStrings.s2_def_two
                    }
                }
            }

            // MARK: - section_one

            /// Translation in fr :
            /// Section Un - Definition Un
            ///
            /// Comment :
            /// This is a comment
            var s1_def_one: String {
                NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "This is a comment")
            }

            /// Translation in fr :
            /// Section Un - Definition Deux
            ///
            /// Comment :
            /// This is a comment
            var s1_def_two: String {
                NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "This is a comment")
            }

            // MARK: - section_two

            /// Translation in fr :
            /// Section Deux - Definition Un
            ///
            /// Comment :
            /// This is a comment
            var s2_def_one: String {
                NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "This is a comment")
            }

            /// Translation in fr :
            /// Section Deux - Definition Deux
            ///
            /// Comment :
            /// This is a comment
            var s2_def_two: String {
                NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "This is a comment")
            }
        }
        """

        if extensionContent != expect {
            print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
        }
        XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
    }

    // MARK: - Extension Content Static
    func testGeneratedExtensionContentWithStaticVar() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"])
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"]),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"])
        ]

        // When
        let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo],
                                                                        defaultLang: "fr",
                                                                        tags: ["ios", "iosonly", "notranslation"],
                                                                        staticVar: true,
                                                                        inputFilename: "myInputFilename",
                                                                        extensionName: "GenStrings",
                                                                        extensionSuffix: "strings")

        // Expect
        let expect = """
        // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion)

        import UIKit

        fileprivate let kStringsFileName = "myInputFilename"

        extension GenStrings {

            enum KeyStrings: String {
                case s1_def_one = "s1_def_one"
                case s1_def_two = "s1_def_two"
                case s2_def_one = "s2_def_one"
                case s2_def_two = "s2_def_two"

                var keyPath: KeyPath<GenStrings, String> {
                    switch self {
                    case .s1_def_one: return \\GenStrings.s1_def_one
                    case .s1_def_two: return \\GenStrings.s1_def_two
                    case .s2_def_one: return \\GenStrings.s2_def_one
                    case .s2_def_two: return \\GenStrings.s2_def_two
                    }
                }
            }

            // MARK: - section_one

            /// Translation in fr :
            /// Section Un - Definition Un
            ///
            /// Comment :
            /// No comment
            static var s1_def_one: String {
                NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "")
            }

            /// Translation in fr :
            /// Section Un - Definition Deux
            ///
            /// Comment :
            /// No comment
            static var s1_def_two: String {
                NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "")
            }

            // MARK: - section_two

            /// Translation in fr :
            /// Section Deux - Definition Un
            ///
            /// Comment :
            /// No comment
            static var s2_def_one: String {
                NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "")
            }

            /// Translation in fr :
            /// Section Deux - Definition Deux
            ///
            /// Comment :
            /// No comment
            static var s2_def_two: String {
                NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "")
            }
        }
        """

        if extensionContent != expect {
            print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
        }
        XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
    }

    func testGeneratedExtensionContentWithStaticVarWithComment() {
        // Given
        let sectionOne = Section(name: "section_one")
        sectionOne.definitions = [
            getDefinition(name: "s1_def_one",
                          translations: ["fr": "Section Un - Definition Un",
                                         "en": "Section One - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s1_def_two",
                          translations: ["fr": "Section Un - Definition Deux",
                                         "en": "Section One - Definition Two"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment")
        ]

        let sectionTwo = Section(name: "section_two")
        sectionTwo.definitions = [
            getDefinition(name: "s2_def_one",
                          translations: ["fr": "Section Deux - Definition Un",
                                         "en": "Section Two - Definition One"],
                          tags: ["ios","iosonly"],
                          comment: "This is a comment"),
            getDefinition(name: "s2_def_two",
                          translations: ["fr": "Section Deux - Definition Deux"],
                          tags: ["notranslation"],
                          comment: "This is a comment")
        ]

        // When
        let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo],
                                                                        defaultLang: "fr",
                                                                        tags: ["ios", "iosonly", "notranslation"],
                                                                        staticVar: true,
                                                                        inputFilename: "myInputFilename",
                                                                        extensionName: "GenStrings",
                                                                        extensionSuffix: "strings")

        // Expect
        let expect = """
        // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion)

        import UIKit

        fileprivate let kStringsFileName = "myInputFilename"

        extension GenStrings {

            enum KeyStrings: String {
                case s1_def_one = "s1_def_one"
                case s1_def_two = "s1_def_two"
                case s2_def_one = "s2_def_one"
                case s2_def_two = "s2_def_two"

                var keyPath: KeyPath<GenStrings, String> {
                    switch self {
                    case .s1_def_one: return \\GenStrings.s1_def_one
                    case .s1_def_two: return \\GenStrings.s1_def_two
                    case .s2_def_one: return \\GenStrings.s2_def_one
                    case .s2_def_two: return \\GenStrings.s2_def_two
                    }
                }
            }

            // MARK: - section_one

            /// Translation in fr :
            /// Section Un - Definition Un
            ///
            /// Comment :
            /// This is a comment
            static var s1_def_one: String {
                NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "This is a comment")
            }

            /// Translation in fr :
            /// Section Un - Definition Deux
            ///
            /// Comment :
            /// This is a comment
            static var s1_def_two: String {
                NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "This is a comment")
            }

            // MARK: - section_two

            /// Translation in fr :
            /// Section Deux - Definition Un
            ///
            /// Comment :
            /// This is a comment
            static var s2_def_one: String {
                NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "This is a comment")
            }

            /// Translation in fr :
            /// Section Deux - Definition Deux
            ///
            /// Comment :
            /// This is a comment
            static var s2_def_two: String {
                NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "This is a comment")
            }
        }
        """

        if extensionContent != expect {
            print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect))
        }
        XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest())
    }
}

