// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

struct A { int i; };
struct B { A a; };
struct C { B bs[5]; };
struct D { C c; };


void Awrite (output A a, int multiplier)
{
    printf ("passing a ref to a A:\n");
    a.i = multiplier;
}



void Aprint (A a)
{
    printf ("a.i = %d\n", a.i);
    printf ("\n");
}



void Bwrite (output B b, int multiplier)
{
    printf ("passing a ref to a B:\n");
    b.a.i = multiplier;
}



void Bprint (B b)
{
    printf ("b.a.i = %d\n", b.a.i);
    printf ("\n");
}



void Barraywrite (output B bs[], int multiplier)
{
    printf ("passing a ref to a B[]:\n");
    for (int i = 0;  i < 5;  ++i)
        bs[i].a.i = i*multiplier;
}



void Barrayprint (B bs[])
{
    for (int i = 0;  i < 5;  ++i)
        printf ("bs[%d].a.i = %d\n", i, bs[i].a.i);
    printf ("\n");
}



void Cwrite (output C c, int multiplier)
{
    printf ("passing a ref to a C:\n");
    for (int i = 0;  i < 5;  ++i)
        c.bs[i].a.i = i*multiplier;
}



void Cprint (C c)
{
    for (int i = 0;  i < 5;  ++i)
        printf ("c.bs[%d].a.i = %d\n", i, c.bs[i].a.i);
    printf ("\n");
}



void Dwrite (output D d, int multiplier)
{
    printf ("passing a ref to a D:\n");
    for (int i = 0;  i < 5;  ++i)
        d.c.bs[i].a.i = i*multiplier;
}



void Dprint (D d)
{
    for (int i = 0;  i < 5;  ++i)
        printf ("d.c.bs[%d].a.i = %d\n", i, d.c.bs[i].a.i);
    printf ("\n");
}



void test_writing (output D d)
{
    d.c.bs[0].a.i = 42;
}



shader test ()
{
    D d;

    printf ("Using a D directly in main:\n");
    for (int i = 0;  i < 5;  ++i)
        d.c.bs[i].a.i = i*1;
    for (int i = 0;  i < 5;  ++i)
        printf ("d.c.bs[%d].a.i = %d\n", i, d.c.bs[i].a.i);
    printf ("\n");

    Dwrite (d, 1);
    Dprint (d);
    Cwrite (d.c, 3);
    Cprint (d.c);
    Barraywrite (d.c.bs, 4);
    Barrayprint (d.c.bs);
    Bwrite (d.c.bs[1], 4);
    Bprint (d.c.bs[1]);

// FIXME -- needs work!  these still don't work properly
//    Awrite (d.c.bs[2].a, 5);
//    Aprint (d.c.bs[2].a);

    // Test assignment of the whole thing
    printf ("Testing assignment of the whole nested structure:\n");
    D d2;
    d2 = d;
    Dwrite (d2, 1);
    Dprint (d2);

    printf ("Testing writing to the innermost struct through function call:\n");
    d.c.bs[0].a.i = 0;
    printf ("  before: d.c.bs[0].a.i = %d\n", d.c.bs[0].a.i);
    test_writing (d);
    printf ("  after:  d.c.bs[0].a.i = %d\n", d.c.bs[0].a.i);
}
