### ----------------------------------------------------
### -- Spreadsheet::XLSX
### -- Licenses: Artistic-2.0
### -- Authors: 
### -- File: t/new-basic.rakutest
### ----------------------------------------------------
use Spreadsheet::XLSX;
use Spreadsheet::XLSX::Exceptions;
use Test;

plan 68;

my Spreadsheet::XLSX $sheet;
lives-ok { $sheet = Spreadsheet::XLSX.new },
        'Can create a new SpreadSheet::XLSX instance';

my $created-at = DateTime.now;

given $sheet.core-properties {
    isa-ok $_, Spreadsheet::XLSX::DocProps::Core;
    is .keys.elems, 0, "new spreadhseet doesn't have any core properties";

    lives-ok { .<creator> = "robot" }, "assginment to a simple string property";
    lives-ok { .<created> = $created-at }, "assginment to a date property";
    .<description> = "foo & bar";

    nok (.<keywords>:exists), "no keywords in a new document";
    .<keywords> = <first second>;
    ok (.<keywords>:exists), "assignment to keywords property vivifies it";
    is-deeply .<keywords>.list, <first second>, "assigned keywords are in there";
    lives-ok { .<keywords>.set(<перший другий>, :lang<uk-UA>) }, "setting keywords in different language";
    is-deeply .<keywords>.pairs.sort,
              (en-US => <first second>, uk-UA => <перший другий>),
              "keywords are set by language";

    throws-like
        { .<foo> },
        X::Spreadsheet::XLSX::NoSuchProperty,
        "reading from an unknown property throws";

    throws-like
        { .<foo> = "doesn't matter" },
        X::Spreadsheet::XLSX::NoSuchProperty,
        "assignment to an unknown property throws";
}

given $sheet.content-types {
    isa-ok $_, Spreadsheet::XLSX::ContentTypes;
    is .defaults.elems, 2, '2 default content types created';
    is .defaults.map(*.extension).sort, <rels xml>,
            'Created expected set of defaults';
    is .overrides.elems, 1, '1 default override created';
    given .overrides[0] {
        is .part-name, '/xl/workbook.xml',
                'Correct workbook override part name';
        is .content-type, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml',
                'Correct workbook override content type';
    }
}

given $sheet.find-relationships('') {
    isa-ok $_, Spreadsheet::XLSX::Relationships,
        'Created a root relationships file';
    given .find-by-type('http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument') {
        is .elems, 1, 'Have a workbook type relationship in the root';
        is .[0].target, 'xl/workbook.xml', 'Relationship point to standard workbook location';
    }
}

given $sheet.workbook {
    isa-ok $_, Spreadsheet::XLSX::Workbook;
    is .worksheets.elems, 0, 'New workbook contains no worksheets';
    is .relationships.find-by-type('http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet').elems,
            0, 'There are no worksheet relations either';

    my $new-sheet-a;
    lives-ok { $new-sheet-a = .create-worksheet('Test A') },
        'Can create a new worksheet';
    isa-ok $new-sheet-a, Spreadsheet::XLSX::Worksheet,
        'The created worksheet is returned';
    is .worksheets.elems, 1,
        'Workbook now has 1 worksheet';
    is .worksheets[0].name, 'Test A',
        'Worksheet has expected name';
    given .relationships.find-by-type('http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') {
        is .elems, 1, 'One new worksheet relation in the workbook relations';
        is .[0].target, $new-sheet-a.archive-path, 'Correct relation target';
    }

    my $new-sheet-b;
    lives-ok { $new-sheet-b = .create-worksheet('Test B') },
            'Can create another new worksheet';
    is .worksheets.elems, 2,
            'Workbook now has 2 worksheets';
    is .worksheets[1].name, 'Test B',
            'Worksheet has expected name';
    isnt $new-sheet-a.id, $new-sheet-b.id,
            'No ID conflict';
    isnt $new-sheet-a.archive-path, $new-sheet-b.archive-path,
            'No filename conflict';

    subtest "Non-set cell doesn't exists", {
        plan 6;
        nok ($new-sheet-a.cells[0;0]:exists), ":exists returns False";
        ok ($new-sheet-a.cells[0;0]:!exists), ":!exists works";
        nok ($new-sheet-a.cells[1;"A"]:exists), ':exists on multi-slice style reference';
        ok ($new-sheet-a.cells[1;"A"]:!exists), ':!exists on multi-slice style reference';
        nok ($new-sheet-a.cells["A1"]:exists), ':exists works with stringy reference';
        ok ($new-sheet-a.cells["A1"]:!exists), ':!exists works with stringy reference';
    }

    $new-sheet-a.cells[0;0] = Spreadsheet::XLSX::Cell::Text.new(value => 'Beef burrito');
    $new-sheet-a.cells[0;1] = Spreadsheet::XLSX::Cell::Number.new(value => 42);
    subtest "Set cell exists", {
        ok ($new-sheet-a.cells[0;0]:exists), ":exists reports True";
        nok ($new-sheet-a.cells[0;0]:!exists), ':!exists reports False';
        ok ($new-sheet-a.cells[1;"A"]:exists), ':exists with multislice-style reference';
        nok ($new-sheet-a.cells[1;"A"]:!exists), ':!exists with multislice-style reference';
        ok ($new-sheet-a.cells["A1"]:exists), ':exists works with stringy reference';
        nok ($new-sheet-a.cells["A1"]:!exists), ':exists works with stringy reference';
    }
    isa-ok $new-sheet-a.cells[0;0], Spreadsheet::XLSX::Cell::Text,
            'Can successfully assign a text cell into the worksheet';
    is $new-sheet-a.cells[0;0].value, 'Beef burrito',
            'Cell value is as expected';
    is $new-sheet-a.cells[1;"A"].value, 'Beef burrito',
       'Cell value is as expected when referenced with [1;"A"]';
    is $new-sheet-a.cells["A1"].value, 'Beef burrito',
       'Cell value is as expected when referenced with symbolic reference';
    isa-ok $new-sheet-a.cells[0;1], Spreadsheet::XLSX::Cell::Number,
            'Can successfully assign a number cell into the worksheet';
    is $new-sheet-a.cells[0;1].value, 42,
            'Cell value is as expected';

    $new-sheet-a.columns[0] = Spreadsheet::XLSX::Worksheet::Column.new:
            :custom-width, :width(32);
    is $new-sheet-a.columns[0].width, 32, 'Can set a column width';
    $new-sheet-a.columns[2] = Spreadsheet::XLSX::Worksheet::Column.new:
            :custom-width, :width(28.5);
}

given $sheet.content-types {
    is .defaults.elems, 2, 'Still 2 default content types after adding sheets';
    is .overrides.elems, 3, 'Now there are 3 overrides';
    given .overrides.grep(*.part-name eq '/xl/worksheets/sheet1.xml') {
        is .elems, 1, 'Have an override for first sheet';
        is .[0].content-type,
            'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
            'Override for first sheet has correct content type';
    }
    given .overrides.grep(*.part-name eq '/xl/worksheets/sheet2.xml') {
        is .elems, 1, 'Have an override for first sheet';
        is .[0].content-type,
                'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
                'Override for first sheet has correct content type';
    }
}

my Blob $serialized;
lives-ok { $serialized = $sheet.to-blob() },
        'Can serialize it into a blob';

my Spreadsheet::XLSX $reloaded;
lives-ok { $reloaded = Spreadsheet::XLSX.load($serialized) },
        'Can reload the serialized sheet';

given $reloaded.worksheets {
    is .elems, 2, 'Workbook has two worksheets';
    is .[0].name, 'Test A', 'First worksheet has correct name';
    is .[1].name, 'Test B', 'Second worksheet has correct name';

    given .[0].cells[0;0] {
        isa-ok $_, Spreadsheet::XLSX::Cell::Text;
        is .value, 'Beef burrito', 'Can successfully read a written text value';
    }
    given .[0].cells[0;1] {
        isa-ok $_, Spreadsheet::XLSX::Cell::Number;
        is .value, 42, 'Can successfully read a written number value';
    }

    given .[0].columns[0] {
        is .custom-width, True, 'Custom width column property saved (1)';
        is .width, 32, 'Custom width saved (1)';
    }
    nok .[0].columns[1].defined, 'No column data for column without anything set';
    given .[0].columns[2] {
        is .custom-width, True, 'Custom width column property saved (3)';
        is .width, 28.5, 'Custom width saved (3)';
    }
}

given $reloaded.core-properties {
    is .<creator>, "robot", "simple core property deserialized";
    is .<description>, "foo & bar", "& in a core property deserialized";
    is .<created>, $created-at, "date core property deserialized";
    is-deeply .<keywords>.pairs.sort,
              (en-US => <first second>, uk-UA => <перший другий>),
              "keywords structure is correctly deserialized";
}

done-testing;


