import * as serverApi from '../../api';

export async function getArtists(filter: string) {
    const query = filter.length > 0 ? {
        prop: serverApi.QueryElemProperty.artistName,
        propOperand: filter,
        propOperator: serverApi.QueryFilterOp.Like,
    } : {};

    var q: serverApi.QueryRequest = {
        query: query,
        offsetsLimits: {
            artistOffset: 0,
            artistLimit: 100,
        },
        ordering: {
            orderBy: {
                type: serverApi.OrderByType.Name,
            },
            ascending: true,
        },
    };

    const requestOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(q),
    };

    return (async () => {
        const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
        let json: any = await response.json();
        const names: string[] = json.artists.map((elem: any) => { return elem.name; });
        return [...new Set(names)];
    })();
}

export async function getAlbums(filter: string) {
    const query = filter.length > 0 ? {
        prop: serverApi.QueryElemProperty.albumName,
        propOperand: filter,
        propOperator: serverApi.QueryFilterOp.Like,
    } : {};

    var q: serverApi.QueryRequest = {
        query: query,
        offsetsLimits: {
            albumOffset: 0,
            albumLimit: 100,
        },
        ordering: {
            orderBy: {
                type: serverApi.OrderByType.Name,
            },
            ascending: true,
        },
    };

    const requestOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(q),
    };

    return (async () => {
        const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
        let json: any = await response.json();
        const names: string[] = json.albums.map((elem: any) => { return elem.name; });
        return [...new Set(names)];
    })();
}

export async function getSongTitles(filter: string) {
    const query = filter.length > 0 ? {
        prop: serverApi.QueryElemProperty.songTitle,
        propOperand: filter,
        propOperator: serverApi.QueryFilterOp.Like,
    } : {};

    var q: serverApi.QueryRequest = {
        query: query,
        offsetsLimits: {
            songOffset: 0,
            songLimit: 100,
        },
        ordering: {
            orderBy: {
                type: serverApi.OrderByType.Name,
            },
            ascending: true,
        },
    };

    const requestOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(q),
    };

    return (async () => {
        const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
        let json: any = await response.json();
        const titles: string[] = json.songs.map((elem: any) => { return elem.title; });
        return [...new Set(titles)];
    })();
}

export async function getTags() {
    var q: serverApi.QueryRequest = {
        query: {},
        offsetsLimits: {
            tagOffset: 0,
            tagLimit: 100,
        },
        ordering: {
            orderBy: {
                type: serverApi.OrderByType.Name,
            },
            ascending: true,
        },
    };

    const requestOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(q),
    };

    return (async () => {
        const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
        let json: any = await response.json();
        const tags = json.tags;

        // Organise the tags into a tree structure.
        // First, we put them in an indexed dict.
        const idxTags: Record<number, any> = {};
        tags.forEach((tag: any) => {
            idxTags[tag.tagId] = {
                ...tag,
                childIds: [],
            }
        })

        // Resolve children.
        tags.forEach((tag: any) => {
            if(tag.parentId && tag.parentId in idxTags) {
                idxTags[tag.parentId].childIds.push(tag.tagId);
            }
        })

        // Return the loose objects again.
        return Object.values(idxTags);
    })();
}