//
//  Album.swift
//  Tag for iTunes
//
//  Created by Kim Wittenburg on 29.05.15.
//  Copyright (c) 2015 Kim Wittenburg. All rights reserved.
//

import Cocoa

/// Represents an album of the
/// [Search API](https://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html).
public class Album: iTunesType {
    
    // MARK: Properties
    
    public let id: iTunesId

    public let name: String
    
    public let censoredName: String
    
    public let viewURL: NSURL
    
    public let artwork: Artwork
    
    public let trackCount: Int
    
    public let releaseDate: NSDate
    
    public let genre: String
    
    public let artistName: String
        
    public private(set) var tracks = [Track]()
    
    // MARK: Initializers
    
    internal init(id: iTunesId, name: String, censoredName: String, viewURL: NSURL, artwork: Artwork, trackCount: Int, releaseDate: NSDate, genre: String, artistName: String) {
        self.id = id
        self.name = name
        self.censoredName = censoredName
        self.viewURL = viewURL
        self.artwork = artwork
        self.trackCount = trackCount
        self.releaseDate = releaseDate
        self.genre = genre
        self.artistName = artistName
    }
    
    public required init(data: [iTunesAPI.Field : AnyObject]) {
        id = data[.CollectionId] as! UInt
        name = data[.CollectionName] as! String
        censoredName = data[.CollectionCensoredName] as! String
        viewURL = NSURL(string: data[.CollectionViewUrl] as! String)!
        
        artwork = Artwork(data: data)
        trackCount = data[.TrackCount] as! Int
        releaseDate = iTunesAPI.sharedDateFormatter.dateFromString(data[.ReleaseDate] as! String)!
        genre = data[.PrimaryGenreName] as! String
        if let artistName = data[.CollectionArtistName] as? String {
            self.artistName = artistName
        } else {
            artistName = data[.ArtistName] as! String
        }
    }
    
    public static var requiredFields: [iTunesAPI.Field] {
        return [.CollectionId, .CollectionName, .CollectionCensoredName, .CollectionViewUrl, .TrackCount, .ReleaseDate, .PrimaryGenreName, .ArtistName]
    }
    
    // MARK: Methods
    
    /// Adds a track to the album.
    internal func addTrack(newTrack: Track) {
        newTrack.album = self
        var index = 0
        for track in tracks {
            if newTrack.discNumber < track.discNumber {
                break
            } else if newTrack.discNumber == track.discNumber {
                if newTrack.trackNumber <= track.trackNumber {
                    break
                }
            }
            ++index
        }
        tracks.insert(newTrack, atIndex: index)
    }
    
    /// Returns wether all tracks in the album have the same artist name as the
    /// album itself.
    public var hasSameArtistNameAsTracks: Bool {
        for track in tracks {
            if artistName != track.artistName {
                return false
            }
        }
        return true
    }
    
    /// Saves the album to iTunes.
    public func save() {
        for track in tracks {
            track.save()
        }
    }
    
    /// Saves the album's artwork to the directory specified in the user's
    /// preferences (See `Preferences` for details).
    public func saveArtwork() throws {
        let url = Preferences.sharedPreferences.artworkTarget
        try artwork.saveToURL(url, filename: name)
    }
    
    /// Returns `true` if all tracks of the album are saved.
    public var saved: Bool {
        for track in tracks {
            if !track.saved {
                return false
            }
        }
        return true
    }
    

}

extension Album: CustomStringConvertible {
    
    public var description: String {
        return "\"\(name)\" (\(tracks.count) tracks)"
    }
    
}

extension Album: Hashable {
    
    public var hashValue: Int {
        return Int(id)
    }
    
}

public func ==(lhs: Album, rhs: Album) -> Bool {
    return lhs === rhs
}