/*
 * Copyright (c) 2021 PSMForums. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.joshuacerdenia.android.nicefeed.util

import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import com.joshuacerdenia.android.nicefeed.data.model.feed.FeedManageable
import com.joshuacerdenia.android.nicefeed.util.extensions.sortedByCategory
import com.rometools.opml.feed.opml.Opml
import com.rometools.opml.feed.opml.Outline
import com.rometools.opml.io.impl.OPML20Generator
import com.rometools.rome.io.WireFeedOutput
import java.io.OutputStreamWriter
import java.net.URL
import java.util.*

class OpmlExporter(
    context: Context,
    private val listener: ExportResultListener
) {

    private val contentResolver = context.contentResolver
    private var feeds = listOf<FeedManageable>()
        get() = field.sortedByCategory()
    private var categories = arrayOf<String>()

    interface ExportResultListener {
        fun onExportAttempted(isSuccessful: Boolean, fileName: String?)
    }

    fun submitFeeds(feeds: List<FeedManageable>) {
        this.feeds = feeds
        categories = feeds.map { feed -> feed.category }.toSet().toTypedArray()
    }

    fun executeExport(uri: Uri) {
        val outputStream = contentResolver.openOutputStream(uri)
        if (outputStream != null) {
            try {
                OutputStreamWriter(outputStream, Charsets.UTF_8).use { writer ->
                    if (feeds.isNotEmpty()) writeOpml(writer)
                }

                contentResolver.query(uri, null, null, null, null)?.use { cursor ->
                    if (cursor.moveToFirst()) {
                        val fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
                        listener.onExportAttempted(true, fileName)
                    }
                }
            } catch (e: Exception) {
                listener.onExportAttempted(false, null)
            }
        } else {
            listener.onExportAttempted(false, null)
        }
    }

    private fun writeOpml(writer: OutputStreamWriter) {
        val opml = Opml().apply {
            feedType = OPML20Generator().type
            encoding = "utf-8"
            created = Date()
            outlines = categories.map { category ->
                Outline(category, null, null).apply {
                    children = feeds.filter { feed -> feed.category == category }.map { feed ->
                        Outline(feed.title, URL(feed.url), URL(feed.website))
                    }
                }
            }
        }

        WireFeedOutput().output(opml, writer)
    }
}