Sparqlpuppy wants to be a SOLID server when it grows up
// sparqlpuppy - an LDP/SOLID Server
// Copyright (C) 2019 Azure <azure@fox.blue>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU Affero 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program.  If not, see
// <https://www.gnu.org/licenses/>.

use http_types::Result;

use rio_api::formatter::TriplesFormatter;
use rio_api::model::{Literal, NamedNode, Triple};
use rio_turtle::TurtleFormatter;

use std::fs::Metadata;
use std::io::Write;
use std::time::SystemTime;

use crate::urls::{
    BASIC_CONTAINER, CONTAINER, CONTAINS, STAT_DIR, STAT_FILE, STAT_MTIME, STAT_SIZE, TYPE,
};

pub fn is_container<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str) -> Result<()> {
    formatter.format(&Triple {
        subject: NamedNode { iri }.into(),
        predicate: NamedNode { iri: TYPE },
        object: NamedNode { iri: CONTAINER }.into(),
    })?;
    Ok(())
}

pub fn is_basic_container<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str) -> Result<()> {
    formatter.format(&Triple {
        subject: NamedNode { iri }.into(),
        predicate: NamedNode { iri: TYPE },
        object: NamedNode {
            iri: BASIC_CONTAINER,
        }
        .into(),
    })?;
    Ok(())
}

pub fn contains<W: Write>(formatter: &mut TurtleFormatter<W>, c: &str, d: &str) -> Result<()> {
    formatter.format(&Triple {
        subject: NamedNode { iri: c }.into(),
        predicate: NamedNode { iri: CONTAINS },
        object: NamedNode { iri: d }.into(),
    })?;
    Ok(())
}

pub fn posix<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str, m: &Metadata) -> Result<()> {
    if m.is_file() {
        formatter.format(&Triple {
            subject: NamedNode { iri }.into(),
            predicate: NamedNode { iri: TYPE },
            object: NamedNode { iri: STAT_FILE }.into(),
        })?;
    } else if m.is_dir() {
        formatter.format(&Triple {
            subject: NamedNode { iri }.into(),
            predicate: NamedNode { iri: TYPE },
            object: NamedNode { iri: STAT_DIR }.into(),
        })?;
    }

    if let Ok(mt) = m.modified() {
        if let Ok(mtime) = mt.duration_since(SystemTime::UNIX_EPOCH) {
            let secs = mtime.as_secs().to_string();
            formatter.format(&Triple {
                subject: NamedNode { iri }.into(),
                predicate: NamedNode { iri: STAT_MTIME },
                object: Literal::Simple { value: &secs }.into(),
            })?;
        }
    }

    let len = m.len().to_string();
    formatter.format(&Triple {
        subject: NamedNode { iri }.into(),
        predicate: NamedNode { iri: STAT_SIZE },
        object: Literal::Simple { value: &len }.into(),
    })?;

    Ok(())
}