use super::{helpers::*, *};

pub fn repository_content_rows(
    contents: Vec<models::ContentsResponse>,
) -> Vec<RepositoryContentRow> {
    let mut rows: Vec<_> = contents
        .into_iter()
        .filter_map(|content| {
            Some(RepositoryContentRow {
                name: content.name?,
                path: content.path?,
                kind: if content.r#type.as_deref() == Some("dir") {
                    RepositoryContentKind::Directory
                } else {
                    RepositoryContentKind::File
                },
                size: content.size.unwrap_or_default(),
            })
        })
        .collect();
    rows.sort_by_key(|row| {
        (
            row.kind != RepositoryContentKind::Directory,
            row.name.to_lowercase(),
        )
    });
    rows
}

pub fn repository_file_page(path: &str, data: Vec<u8>) -> RepositoryFilePage {
    let name = path.rsplit('/').next().unwrap_or("Preview").to_string();
    let extension = path.rsplit('.').next().unwrap_or_default().to_lowercase();
    let language = source_language(path).unwrap_or_default().to_string();
    let markdown = matches!(extension.as_str(), "md" | "markdown" | "mdown" | "mkd");
    let media = matches!(
        extension.as_str(),
        "apng"
            | "avi"
            | "bmp"
            | "flac"
            | "gif"
            | "heic"
            | "heif"
            | "jpeg"
            | "jpg"
            | "m4a"
            | "m4v"
            | "mkv"
            | "mov"
            | "mp3"
            | "mp4"
            | "mpeg"
            | "mpg"
            | "ogg"
            | "pdf"
            | "png"
            | "tif"
            | "tiff"
            | "wav"
            | "webm"
            | "webp"
    );
    if media {
        return RepositoryFilePage {
            name,
            kind: RepositoryFileKind::Preview,
            language,
            text: String::new(),
            data,
        };
    }
    match String::from_utf8(data) {
        Ok(text) => RepositoryFilePage {
            name,
            kind: if markdown {
                RepositoryFileKind::Markdown
            } else {
                RepositoryFileKind::Source
            },
            language,
            text,
            data: Vec::new(),
        },
        Err(error) => RepositoryFilePage {
            name,
            kind: RepositoryFileKind::Preview,
            language,
            text: String::new(),
            data: error.into_bytes(),
        },
    }
}

pub fn diff_page(path: &str, diff: diff::Parsed) -> DiffPage {
    DiffPage {
        title: path.rsplit('/').next().unwrap_or(path).into(),
        columns: diff.columns.min(u32::MAX as usize) as u32,
        lines: diff
            .lines
            .into_iter()
            .map(|line| DiffLine {
                old_number: line.old_number,
                new_number: line.new_number,
                text: line.text,
                kind: match line.kind {
                    "addition" => DiffLineKind::Addition,
                    "removal" => DiffLineKind::Removal,
                    "hunk" => DiffLineKind::Hunk,
                    "header" => DiffLineKind::Header,
                    _ => DiffLineKind::Context,
                },
            })
            .collect(),
    }
}
