/* src/processes/cgroup.rs
 *
 * Copyright 2025 Mission Center Developers
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

use std::fmt::Write;

use arrayvec::ArrayString;

use super::MAX_U32_LEN;

pub fn open(pid: u32) -> Option<std::fs::File> {
    const MAX_PATH_LEN: usize = "/proc/".len() + "/cgroup".len() + MAX_U32_LEN;

    let mut path: ArrayString<MAX_PATH_LEN> = ArrayString::new();
    let _ = write!(path, "/proc/{}/cgroup", pid);

    let io_file = match std::fs::OpenOptions::new().read(true).open(path) {
        Ok(f) => f,
        Err(e) => {
            log::warn!("Failed to open `cgroup` file for process {}: {}", pid, e,);
            return None;
        }
    };

    Some(io_file)
}

pub fn parse_for(pid: u32, cgroup_file_content: &str) -> Option<String> {
    let mut cgroup = None;

    let mut end_match: ArrayString<{ MAX_U32_LEN + 1 }> = ArrayString::new();
    let _ = write!(end_match, "/{}", pid);

    let cfc = cgroup_file_content
        .trim()
        .split(':')
        .nth(2)
        .unwrap_or("/")
        .trim_start_matches('/')
        .trim_end_matches(end_match.as_str());

    let cgroup_path = std::path::Path::new("/sys/fs/cgroup").join(cfc);
    if !cfc.is_empty() && cgroup_path.exists() && cgroup_path.is_dir() {
        let app_scope = cfc.split('/').last().unwrap_or("");
        if (app_scope.starts_with("app") || app_scope.starts_with("snap"))
            && app_scope.ends_with(".scope")
        {
            cgroup = Some(cgroup_path.to_string_lossy().to_string());
        }
    }

    cgroup
}
