/*
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
*/

const { describe, it, beforeEach } = require('node:test');
const assert = require('node:assert');

const PBXProject = require('../lib/pbxProject');
let project;

const findChildInGroup = function (obj, target) {
    let found = false;

    for (let i = 0, j = obj.children.length; i < j; i++) {
        if (obj.children[i].value === target) {
            found = true;
            break;
        }
    }

    return found;
};

const findByName = function (obj, target) {
    let found = false;
    for (const property in obj) {
        if (!/comment/.test(property)) {
            const value = obj[property];
            if (value.name === target) {
                found = true;
            }
        }
    }
    return found;
};

describe('variantGroup', () => {
    beforeEach(() => {
        project = new PBXProject('test/parser/projects/variantgroup.pbxproj');
        project.parseSync();
    });

    describe('getVariantGroupByKey', () => {
        it('should return PBXVariantGroup for Localizable.strings', () => {
            const groupKey = project.findPBXVariantGroupKey({ name: 'Localizable.strings' });
            const group = project.getPBXVariantGroupByKey(groupKey);
            assert.ok(group.name === 'Localizable.strings');
        });
    });

    describe('createVariantGroup', () => {
        it('should create a new Test Variant Group', () => {
            delete project.getPBXObject('PBXVariantGroup');

            let found = false;
            let groups = project.getPBXObject('PBXVariantGroup');

            found = findByName(groups, 'Test');
            assert.ok(found === false);

            let group = project.findPBXVariantGroupKey({ name: 'Test' });
            assert.ok(group === undefined);

            project.pbxCreateVariantGroup('Test');

            groups = project.getPBXObject('PBXVariantGroup');
            found = findByName(groups, 'Test');
            assert.ok(found === true);

            group = project.findPBXVariantGroupKey({ name: 'Test' });
            assert.ok(typeof group === 'string');
        });
    });

    describe('findVariantGroupKey', () => {
        it('should return a valid group key', () => {
            const keyByName = project.findPBXVariantGroupKey({ name: 'Localizable.strings' });
            const nonExistingKey = project.findPBXVariantGroupKey({ name: 'Foo' });

            assert.ok(keyByName === '07E3BDBC1DF1DEA500E49912');
            assert.ok(nonExistingKey === undefined);
        });
    });

    describe('createLocalisationVariantGroup', () => {
        it('should create a new localisation variationgroup then add group to Resources group', () => {
            delete project.getPBXObject('PBXVariantGroup');

            const localizationVariantGp = project.addLocalizationVariantGroup('InfoPlist.strings');

            const resourceGroupKey = project.findPBXGroupKey({ name: 'Resources' });
            const resourceGroup = project.getPBXGroupByKey(resourceGroupKey);
            const foundInResourcesGroup = findChildInGroup(resourceGroup, localizationVariantGp.fileRef);
            assert.ok(foundInResourcesGroup);

            let foundInResourcesBuildPhase = false;
            const sources = project.pbxResourcesBuildPhaseObj();
            for (let i = 0, j = sources.files.length; i < j; i++) {
                const file = sources.files[i];
                if (file.value === localizationVariantGp.uuid) {
                    foundInResourcesBuildPhase = true;
                }
            }
            assert.ok(foundInResourcesBuildPhase);
        });
    });

    describe('addResourceFileToLocalisationGroup', () => {
        it('should add resource file to the TestVariantGroup group', () => {
            const infoPlistVarGp = project.addLocalizationVariantGroup('InfoPlist.strings');
            const testKey = infoPlistVarGp.fileRef;
            const file = project.addResourceFile('Resources/en.lproj/Localization.strings', { variantGroup: true }, testKey);

            const foundInLocalisationVariantGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef);
            assert.ok(foundInLocalisationVariantGroup);

            let foundInResourcesBuildPhase = false;
            const sources = project.pbxResourcesBuildPhaseObj();
            for (let i = 0, j = sources.files.length; i < j; i++) {
                const sourceFile = sources.files[i];
                if (sourceFile.value === file.fileRef) {
                    foundInResourcesBuildPhase = true;
                }
            }
            assert.ok(!foundInResourcesBuildPhase);

            const buildFileSection = project.pbxBuildFileSection();
            assert.ok(buildFileSection[file.uuid] === undefined);
        });
    });

    describe('removeResourceFileFromGroup', () => {
        it('should add resource file then remove resource file from Localizable.strings group', () => {
            const testKey = project.findPBXVariantGroupKey({ name: 'Localizable.strings' });
            const file = project.addResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey);

            let foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef);
            assert.ok(foundInGroup);

            project.removeResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey);

            foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef);
            assert.ok(!foundInGroup);
        });
    });
});
