use keeshond_datapack::{ReadSeek, DataObject, DataError, DataStore, TrustPolicy};
use keeshond_datapack::source::{FilesystemSource, Source, SourceManager, TrustLevel};

use std::io::Read;
use std::cell::RefCell;
use std::rc::Rc;

struct TextData
{
    text : String
}

impl DataObject for TextData
{
    fn folder_name() -> &'static str where Self : Sized
    {
        "text"
    }
    fn trust_policy() -> TrustPolicy { TrustPolicy::UntrustedOk }
    fn want_file(_pathname : &str) -> bool where Self : Sized
    {
        true
    }
    fn from_io(mut reader: Box<dyn ReadSeek>, _full_pathname : &str, _source : &mut Box<dyn Source>) -> Result<Self, DataError> where Self : Sized
    {
        let mut text = String::new();
        
        let result = reader.read_to_string(&mut text);
        
        if result.is_err()
        {
            return Err(DataError::BadData("Couldn't read string".to_string()));
        }
        
        Ok(TextData{ text })
    }
}

fn main()
{
    println!("Listing items in mypackage/text:");
    
    let mut source = FilesystemSource::new("examples", TrustLevel::TrustedSource);
    let iter = source.iter_entries("mypackage", "text");
    
    for entry in iter
    {
        match entry
        {
            Ok(pathname) => println!("{}", pathname),
            Err(error) => println!("Error: {}", error)
        }
    }
    
    println!("Loading files from mypackage/text...");
    
    let source_manager = Rc::new(RefCell::new(SourceManager::new()));
    source_manager.borrow_mut().add_source(Box::new(source));
    
    let mut store = DataStore::<TextData>::new(source_manager);
    
    store.load_package("mypackage").expect("Failed to load package.");
    
    for name in &["emoji.txt", "missingfile.txt", "loremipsum.txt"]
    {
        match store.get_id("mypackage", name)
        {
            Ok(id) =>
            {
                println!("Contents of {}:", name);
                match store.get(id)
                {
                    Some(data) => println!("{}", data.text),
                    None => println!("(not found)"),
                }
            }
            Err(error) =>
            {
                println!("Error for {}:\n{}", name, error);
            }
        }
        
        println!("");
    }
}
