import Foundation

final class Post: Item {

    @Published
    var isDraft: Bool

    @Published
    var createdDate: Date

    @Published
    var startDate: Date

    @Published
    var hasEndDate: Bool

    @Published
    var endDate: Date

    /**
     The tags associated with the post

     This list is only used if ``linkedPage`` is `nil`,
     otherwise the tag list of the linked page is used.
     */
    @Published
    var tags: [Tag]

    @Published
    var german: LocalizedPost

    @Published
    var english: LocalizedPost

    /// The page linked to by this post
    @Published
    var linkedPage: Page?

    init(content: Content,
         id: String,
         isDraft: Bool,
         createdDate: Date,
         startDate: Date,
         endDate: Date?,
         tags: [Tag],
         german: LocalizedPost,
         english: LocalizedPost,
         linkedPage: Page? = nil) {
        self.isDraft = isDraft
        self.createdDate = createdDate
        self.startDate = startDate
        self.hasEndDate = endDate != nil
        self.endDate = endDate ?? startDate
        self.tags = tags
        self.german = german
        self.english = english
        self.linkedPage = linkedPage
        super.init(content: content, id: id)
    }

    // MARK: Tags

    func usedTags() -> [Tag] {
        linkedPage?.tags ?? tags
    }

    /**
     Check if a tag is associated with this post.

     If the post is linked to a page, then the tags of the page are checked.
     */
    func contains(_ tag: Tag) -> Bool {
        guard let linkedPage else {
            return tags.contains(tag)
        }
        return linkedPage.tags.contains(tag)
    }

    func toggle(_ tag: Tag) {
        if let linkedPage {
            linkedPage.toggle(tag)
            return
        }
        guard let index = tags.firstIndex(of: tag) else {
            tags.append(tag)
            return
        }
        tags.remove(at: index)
    }

    func remove(_ tag: Tag) {
        if let linkedPage {
            linkedPage.remove(tag)
            return
        }
        tags.remove(tag)
    }

    func associate(_ tag: Tag) {
        if let linkedPage {
            linkedPage.associate(tag)
            return
        }
        guard !tags.contains(tag) else {
            return
        }
        tags.append(tag)
    }

    func localized(in language: ContentLanguage) -> LocalizedPost {
        switch language {
        case .english: return english
        case .german: return german
        }
    }

    func isValid(id: String) -> Bool {
        !id.isEmpty &&
        content.isValidIdForTagOrPageOrPost(id) &&
        content.isNewIdForPost(id)
    }

    @discardableResult
    func update(id newId: String) -> Bool {
        guard content.storage.move(post: id, to: newId) else {
            print("Failed to move file of post \(id)")
            return false
        }
        id = newId
        return true
    }
}

extension Post: DateItem {

}
