<commit_before>package com.simplemobiletools.gallery.extensions

import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
import com.simplemobiletools.gallery.activities.SettingsActivity
import com.simplemobiletools.gallery.helpers.Config
import com.simplemobiletools.gallery.helpers.IMAGES
import com.simplemobiletools.gallery.helpers.NOMEDIA
import com.simplemobiletools.gallery.helpers.VIDEOS
import com.simplemobiletools.gallery.models.Medium
import java.io.File
import java.util.*

fun Context.getRealPathFromURI(uri: Uri): String? {
    var cursor: Cursor? = null
    try {
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        cursor = contentResolver.query(uri, projection, null, null, null)
        if (cursor?.moveToFirst() == true) {
            val index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            return cursor.getString(index)
        }
    } catch (e: Exception) {
    } finally {
        cursor?.close()
    }
    return null
}

fun Context.getHumanizedFilename(path: String): String {
    val humanized = humanizePath(path)
    return humanized.substring(humanized.lastIndexOf("/") + 1)
}

fun Context.launchSettings() {
    startActivity(Intent(this, SettingsActivity::class.java))
}

fun Context.getParents(): ArrayList<String> {
    val uri = MediaStore.Files.getContentUri("external")
    val columns = arrayOf(MediaStore.Files.FileColumns.PARENT, MediaStore.Images.Media.DATA)
    val where = "${MediaStore.Images.Media.DATA} IS NOT NULL) GROUP BY (${MediaStore.Files.FileColumns.PARENT} "
    val parentsSet = TreeSet<String>(String.CASE_INSENSITIVE_ORDER)

    var cursor: Cursor? = null
    try {
        cursor = contentResolver.query(uri, columns, where, null, null)
        if (cursor?.moveToFirst() == true) {
            do {
                val curPath = cursor.getStringValue(MediaStore.Images.Media.DATA) ?: continue
                val parent = File(curPath).parent ?: continue
                parentsSet.add(parent)
            } while (cursor.moveToNext())
        }
    } finally {
        cursor?.close()
    }

    val noMediaFolders = getNoMediaFolders()
    val parents = ArrayList<String>()
    if (config.shouldShowHidden) {
        parentsSet.addAll(noMediaFolders)
    }

    parentsSet.addAll(config.includedFolders)

    parentsSet.filterTo(parents, {
        val file = File(it)
        if (file.isDirectory && file.canonicalFile == file.absoluteFile) {  // filter out symbolic links too
            if (!config.shouldShowHidden) {
                isFolderVisible(it, noMediaFolders)
            } else
                true
        } else {
            false
        }
    })

    return parents
}

private fun isFolderVisible(path: String, noMediaFolders: ArrayList<String>): Boolean {
    return if (path.contains("/.")) {
        false
    } else {
        !noMediaFolders.any { path.startsWith(it) }
    }
}

fun Context.getNoMediaFolders(): ArrayList<String> {
    val folders = ArrayList<String>()
    val noMediaCondition = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ${MediaStore.Files.FileColumns.MEDIA_TYPE_NONE}"

    val uri = MediaStore.Files.getContentUri("external")
    val columns = arrayOf(MediaStore.Files.FileColumns.DATA)
    val where = "$noMediaCondition AND ${MediaStore.Files.FileColumns.TITLE} LIKE ?"
    val args = arrayOf("%$NOMEDIA%")
    var cursor: Cursor? = null

    try {
        cursor = contentResolver.query(uri, columns, where, args, null)
        if (cursor?.moveToFirst() == true) {
            do {
                val path = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)) ?: continue
                val noMediaFile = File(path)
                if (noMediaFile.exists())
                    folders.add(noMediaFile.parent)
            } while (cursor.moveToNext())
        }
    } finally {
        cursor?.close()
    }

    return folders
}

val Context.config: Config get() = Config.newInstance(this)

fun Context.getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean): ArrayList<Medium> {
    val curMedia = ArrayList<Medium>()
    val showMedia = config.showMedia
    val showHidden = config.shouldShowHidden
    val projection = arrayOf(MediaStore.Images.Media._ID,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.DATE_TAKEN,
            MediaStore.Images.Media.DATE_MODIFIED,
            MediaStore.Images.Media.DATA,
            MediaStore.Images.Media.SIZE)
    val uri = MediaStore.Files.getContentUri("external")
    val selection = if (curPath.isEmpty()) null else "(${MediaStore.Images.Media.DATA} LIKE ? AND ${MediaStore.Images.Media.DATA} NOT LIKE ?)"
    val selectionArgs = if (curPath.isEmpty()) null else arrayOf("$curPath/%", "$curPath/%/%")

    val cur = contentResolver.query(uri, projection, selection, selectionArgs, getSortingForFolder(curPath))
    if (cur.moveToFirst()) {
        var filename: String
        var path: String
        var dateTaken: Long
        var dateModified: Long
        var size: Long
        var isImage: Boolean
        var isVideo: Boolean

        do {
            path = cur.getStringValue(MediaStore.Images.Media.DATA)
            size = cur.getLongValue(MediaStore.Images.Media.SIZE)
            if (size == 0L) {
                size = File(path).length()
            }

            if (size <= 0L) {
                continue
            }

            filename = cur.getStringValue(MediaStore.Images.Media.DISPLAY_NAME) ?: ""
            if (filename.isEmpty())
                filename = path.getFilenameFromPath()

            isImage = filename.isImageFast() || filename.isGif()
            isVideo = if (isImage) false else filename.isVideoFast()

            if (!isImage && !isVideo)
                continue

            if (isVideo && (isPickImage || showMedia == IMAGES))
                continue

            if (isImage && (isPickVideo || showMedia == VIDEOS))
                continue

            if (!showHidden && filename.startsWith('.'))
                continue

            dateTaken = cur.getLongValue(MediaStore.Images.Media.DATE_TAKEN)
            dateModified = cur.getIntValue(MediaStore.Images.Media.DATE_MODIFIED) * 1000L

            val medium = Medium(filename, path, isVideo, dateModified, dateTaken, size)
            curMedia.add(medium)
        } while (cur.moveToNext())
    }
    cur.close()

    Medium.sorting = config.getFileSorting(curPath)
    curMedia.sort()

    return curMedia<commit_msg>catch exceptions thrown during media obtaining<commit_after>package com.simplemobiletools.gallery.extensions

import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
import com.simplemobiletools.gallery.activities.SettingsActivity
import com.simplemobiletools.gallery.helpers.Config
import com.simplemobiletools.gallery.helpers.IMAGES
import com.simplemobiletools.gallery.helpers.NOMEDIA
import com.simplemobiletools.gallery.helpers.VIDEOS
import com.simplemobiletools.gallery.models.Medium
import java.io.File
import java.util.*

fun Context.getRealPathFromURI(uri: Uri): String? {
    var cursor: Cursor? = null
    try {
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        cursor = contentResolver.query(uri, projection, null, null, null)
        if (cursor?.moveToFirst() == true) {
            val index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            return cursor.getString(index)
        }
    } catch (e: Exception) {
    } finally {
        cursor?.close()
    }
    return null
}

fun Context.getHumanizedFilename(path: String): String {
    val humanized = humanizePath(path)
    return humanized.substring(humanized.lastIndexOf("/") + 1)
}

fun Context.launchSettings() {
    startActivity(Intent(this, SettingsActivity::class.java))
}

fun Context.getParents(): ArrayList<String> {
    val uri = MediaStore.Files.getContentUri("external")
    val columns = arrayOf(MediaStore.Files.FileColumns.PARENT, MediaStore.Images.Media.DATA)
    val where = "${MediaStore.Images.Media.DATA} IS NOT NULL) GROUP BY (${MediaStore.Files.FileColumns.PARENT} "
    val parentsSet = TreeSet<String>(String.CASE_INSENSITIVE_ORDER)

    var cursor: Cursor? = null
    try {
        cursor = contentResolver.query(uri, columns, where, null, null)
        if (cursor?.moveToFirst() == true) {
            do {
                val curPath = cursor.getStringValue(MediaStore.Images.Media.DATA) ?: continue
                val parent = File(curPath).parent ?: continue
                parentsSet.add(parent)
            } while (cursor.moveToNext())
        }
    } finally {
        cursor?.close()
    }

    val noMediaFolders = getNoMediaFolders()
    val parents = ArrayList<String>()
    if (config.shouldShowHidden) {
        parentsSet.addAll(noMediaFolders)
    }

    parentsSet.addAll(config.includedFolders)

    parentsSet.filterTo(parents, {
        val file = File(it)
        if (file.isDirectory && file.canonicalFile == file.absoluteFile) {  // filter out symbolic links too
            if (!config.shouldShowHidden) {
                isFolderVisible(it, noMediaFolders)
            } else
                true
        } else {
            false
        }
    })

    return parents
}

private fun isFolderVisible(path: String, noMediaFolders: ArrayList<String>): Boolean {
    return if (path.contains("/.")) {
        false
    } else {
        !noMediaFolders.any { path.startsWith(it) }
    }
}

fun Context.getNoMediaFolders(): ArrayList<String> {
    val folders = ArrayList<String>()
    val noMediaCondition = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ${MediaStore.Files.FileColumns.MEDIA_TYPE_NONE}"

    val uri = MediaStore.Files.getContentUri("external")
    val columns = arrayOf(MediaStore.Files.FileColumns.DATA)
    val where = "$noMediaCondition AND ${MediaStore.Files.FileColumns.TITLE} LIKE ?"
    val args = arrayOf("%$NOMEDIA%")
    var cursor: Cursor? = null

    try {
        cursor = contentResolver.query(uri, columns, where, args, null)
        if (cursor?.moveToFirst() == true) {
            do {
                val path = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)) ?: continue
                val noMediaFile = File(path)
                if (noMediaFile.exists())
                    folders.add(noMediaFile.parent)
            } while (cursor.moveToNext())
        }
    } finally {
        cursor?.close()
    }

    return folders
}

val Context.config: Config get() = Config.newInstance(this)

fun Context.getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean): ArrayList<Medium> {
    val curMedia = ArrayList<Medium>()
    val showMedia = config.showMedia
    val showHidden = config.shouldShowHidden
    val projection = arrayOf(MediaStore.Images.Media._ID,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.DATE_TAKEN,
            MediaStore.Images.Media.DATE_MODIFIED,
            MediaStore.Images.Media.DATA,
            MediaStore.Images.Media.SIZE)
    val uri = MediaStore.Files.getContentUri("external")
    val selection = if (curPath.isEmpty()) null else "(${MediaStore.Images.Media.DATA} LIKE ? AND ${MediaStore.Images.Media.DATA} NOT LIKE ?)"
    val selectionArgs = if (curPath.isEmpty()) null else arrayOf("$curPath/%", "$curPath/%/%")

    val cur = contentResolver.query(uri, projection, selection, selectionArgs, getSortingForFolder(curPath))
    try {
        if (cur.moveToFirst()) {
            var filename: String
            var path: String
            var dateTaken: Long
            var dateModified: Long
            var size: Long
            var isImage: Boolean
            var isVideo: Boolean


            do {
                try {
                    path = cur.getStringValue(MediaStore.Images.Media.DATA)
                    size = cur.getLongValue(MediaStore.Images.Media.SIZE)
                    if (size == 0L) {
                        size = File(path).length()
                    }

                    if (size <= 0L) {
                        continue
                    }

                    filename = cur.getStringValue(MediaStore.Images.Media.DISPLAY_NAME) ?: ""
                    if (filename.isEmpty())
                        filename = path.getFilenameFromPath()

                    isImage = filename.isImageFast() || filename.isGif()
                    isVideo = if (isImage) false else filename.isVideoFast()

                    if (!isImage && !isVideo)
                        continue

                    if (isVideo && (isPickImage || showMedia == IMAGES))
                        continue

                    if (isImage && (isPickVideo || showMedia == VIDEOS))
                        continue

                    if (!showHidden && filename.startsWith('.'))
                        continue

                    dateTaken = cur.getLongValue(MediaStore.Images.Media.DATE_TAKEN)
                    dateModified = cur.getIntValue(MediaStore.Images.Media.DATE_MODIFIED) * 1000L

                    val medium = Medium(filename, path, isVideo, dateModified, dateTaken, size)
                    curMedia.add(medium)
                } catch (e: Exception) {
                    continue
                }
            } while (cur.moveToNext())
        }
    } finally {
        cur.close()
    }

    Medium.sorting = config.getFileSorting(curPath)
    curMedia.sort()

    return curMedia
{'fraction_non_alphanumeric': 0.1050302093578755, 'fraction_numerical': 0.0009835604889700718, 'mean_word_length': 2.4872611464968153, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '419794', 'n_tokens_mistral': 4059, 'n_tokens_neox': 3907, 'n_words': 795}