package com.gh.gamecenter.xapk.io

import android.content.Context
import android.net.Uri
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile
import com.gh.gamecenter.xapk.XApkUnZipTask
import com.gh.gamecenter.xapk.data.XApkManifest
import java.io.File
import androidx.core.net.toUri

class OBBDocOutput(
    private val context: Context
) : XApkFileOutput<Unit> {

    override fun output(
        writer: XApkUnZipTask.XApkWriter,
        manifest: XApkManifest
    ) {

        val expansions = manifest.expansions

        if (expansions.isNullOrEmpty()) {
            return
        }

        ANDROID_OBB_URI.toUri()
            .takeIf { uri ->
                // 判断是否具有obb文件夹读写权限
                context
                    .contentResolver
                    .persistedUriPermissions
                    .any { it.uri == uri }
            }
            ?.let {
                DocumentFile.fromTreeUri(context, it)!!
            }
            ?.also { doc ->
                expansions.forEach { expansion ->
                    expansion.installPath
                        .let {
                            if (it.startsWith(ANDROID_OBB_SEGMENT)) {// 截取Android/obb后面的路径
                                it.substring(ANDROID_OBB_SEGMENT.length + 1)
                            } else {
                                it
                            }.split(File.separatorChar)
                        }
                        .let {
                            // 递归创建OBB数据文件在Android/obb文件夹下对应的路路径
                            it.foldIndexed(doc) { i, f, s ->
                                val child = f.findFile(s)
                                if (child == null || !child.exists()) {
                                    if (i == it.lastIndex) {
                                        f.createFile(ANDROID_OBB_MIME_TYPE, s)!!
                                    } else {
                                        f.createDirectory(s)!!
                                    }
                                } else child
                            }
                        }
                        .let {
                            // 开启文件输出流
                            context.contentResolver.openOutputStream(it.uri)!!
                        }
                        .also {
                            writer.write(expansion.file, it)
                        }
                }
            }
            ?: throw OBBDocOutputUriNotGrantedException(
                ERROR_OBB_URI_NOT_GRANTED.format(
                    ANDROID_OBB_URI
                )
            )
    }

    companion object {
        private const val ANDROID_DOCS_AUTHORITY = "com.android.externalstorage.documents"
        private const val ANDROID_OBB_SEGMENT = "Android/obb"
        private const val ANDROID_OBB_MIME_TYPE = "application/octet-stream"

        private const val ERROR_OBB_URI_NOT_GRANTED = "未授予OBB文件夹控制权限，OBB授权URI路径：%s"

        const val ANDROID_OBB_URI = "content://$ANDROID_DOCS_AUTHORITY/tree/primary%3AAndroid%2Fobb"
        const val ANDROID_OBB_DOC_STYLE_URI = "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fobb/document/primary%3AAndroid%2Fobb"
    }
}