package com.rssuper.parsing

import com.rssuper.models.Feed
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import java.io.StringReader
import java.util.Date

object FeedParser {

    fun parse(xml: String, feedUrl: String): ParseResult {
        val feedType = detectFeedType(xml)
        
        return when (feedType) {
            FeedType.RSS -> {
                val feed = RSSParser.parse(xml, feedUrl)
                ParseResult(FeedType.RSS, feed)
            }
            FeedType.Atom -> {
                val feed = AtomParser.parse(xml, feedUrl)
                ParseResult(FeedType.Atom, feed)
            }
        }
    }

    fun parseAsync(xml: String, feedUrl: String, callback: (Result<ParseResult>) -> Unit) {
        try {
            val result = parse(xml, feedUrl)
            callback(Result.success(result))
        } catch (e: Exception) {
            callback(Result.failure(e))
        }
    }

    private fun detectFeedType(xml: String): FeedType {
        val factory = XmlPullParserFactory.newInstance()
        factory.isNamespaceAware = true
        val parser = factory.newPullParser()
        parser.setInput(StringReader(xml))

        var eventType = parser.eventType
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {
                val tagName = parser.name
                return when {
                    tagName.equals("rss", ignoreCase = true) -> FeedType.RSS
                    tagName.equals("feed", ignoreCase = true) -> FeedType.Atom
                    tagName.equals("RDF", ignoreCase = true) -> FeedType.RSS
                    else -> {
                        val namespace = parser.namespace
                        if (namespace != null && namespace.isNotEmpty()) {
                            when {
                                tagName.equals("rss", ignoreCase = true) -> FeedType.RSS
                                tagName.equals("feed", ignoreCase = true) -> FeedType.Atom
                                else -> throw FeedParsingError.UnsupportedFeedType
                            }
                        } else {
                            throw FeedParsingError.UnsupportedFeedType
                        }
                    }
                }
            }
            eventType = parser.next()
        }
        throw FeedParsingError.UnsupportedFeedType
    }
}
