package controller

import (
    "arimelody-web/model"

    "github.com/jmoiron/sqlx"
)

// DATABASE

func GetTrack(db *sqlx.DB, id string) (*model.Track, error) {
    var track = model.Track{}

    stmt, _ := db.Preparex("SELECT * FROM musictrack WHERE id=$1")
    err := stmt.Get(&track, id)
    if err != nil {
        return nil, err
    }
    return &track, nil
}

func GetAllTracks(db *sqlx.DB) ([]*model.Track, error) {
    var tracks = []*model.Track{}

    err := db.Select(&tracks, "SELECT * FROM musictrack")
    if err != nil {
        return nil, err
    }

    return tracks, nil
}

func GetOrphanTracks(db *sqlx.DB) ([]*model.Track, error) {
    var tracks = []*model.Track{}

    err := db.Select(&tracks, "SELECT * FROM musictrack WHERE id NOT IN (SELECT track FROM musicreleasetrack)")
    if err != nil {
        return nil, err
    }

    return tracks, nil
}

func GetTracksNotOnRelease(db *sqlx.DB, releaseID string) ([]*model.Track, error) {
    var tracks = []*model.Track{}

    err := db.Select(&tracks,
        "SELECT * FROM musictrack "+
        "WHERE id NOT IN "+
        "(SELECT track FROM musicreleasetrack WHERE release=$1)",
        releaseID)
    if err != nil {
        return nil, err
    }

    return tracks, nil
}

func GetTrackReleases(db *sqlx.DB, trackID string, full bool) ([]*model.Release, error) {
    var releases = []*model.Release{}

    err := db.Select(&releases,
        "SELECT id,title,type,release_date,artwork,buylink "+
        "FROM musicrelease "+
        "JOIN musicreleasetrack ON release=id "+
        "WHERE track=$1 "+
        "ORDER BY release_date",
        trackID,
    )
    if err != nil {
        return nil, err
    }

    type NamePrimary struct {
        Name    string  `json:"name"`
        Primary bool    `json:"primary" db:"is_primary"`
    }
    for _, release := range releases {
        // get artists
        credits := []NamePrimary{}
        err := db.Select(&credits,
            "SELECT name,is_primary FROM artist "+
            "JOIN musiccredit ON artist=artist.id "+
            "JOIN musicrelease ON release=musicrelease.id "+
            "WHERE musicrelease.id=$1", release.ID)
        if err != nil {
            return nil, err
        }
        for _, credit := range credits {
            release.Credits = append(release.Credits, &model.Credit{
                Artist: model.Artist{
                    Name: credit.Name,
                },
                Primary: credit.Primary,
            })
        }

        // get tracks
        tracks := []string{}
        err = db.Select(&tracks, "SELECT track FROM musicreleasetrack WHERE release=$1", release.ID)
        if err != nil {
            return nil, err
        }
        for _, trackID := range tracks {
            release.Tracks = append(release.Tracks, &model.Track{
                ID: trackID,
            })
        }
    }

    return releases, nil
}

func PullOrphanTracks(db *sqlx.DB) ([]*model.Track, error) {
    var tracks = []*model.Track{}

    err := db.Select(&tracks,
        "SELECT id, title, description, lyrics, preview_url FROM musictrack "+
        "WHERE id NOT IN "+
        "(SELECT track FROM musicreleasetrack)",
    )
    if err != nil {
        return nil, err
    }

    return tracks, nil
}

func CreateTrack(db *sqlx.DB, track *model.Track) (string, error) {
    var trackID string
    err := db.QueryRow(
        "INSERT INTO musictrack (title, description, lyrics, preview_url) "+
        "VALUES ($1, $2, $3, $4) "+
        "RETURNING id",
        track.Title,
        track.Description,
        track.Lyrics,
        track.PreviewURL,
    ).Scan(&trackID)
    if err != nil {
        return "", err
    }

    return trackID, nil
}

func UpdateTrack(db *sqlx.DB, track *model.Track) error {
    _, err := db.Exec(
        "UPDATE musictrack "+
        "SET title=$2, description=$3, lyrics=$4, preview_url=$5 "+
        "WHERE id=$1",
        track.ID,
        track.Title,
        track.Description,
        track.Lyrics,
        track.PreviewURL,
    )
    if err != nil {
        return err
    }

    return nil
}

func DeleteTrack(db *sqlx.DB, trackID string) error {
    _, err := db.Exec(
        "DELETE FROM musictrack "+
        "WHERE id=$1",
        trackID,
    )
    if err != nil {
        return err
    }

    return nil
}
