namespace ImageResources {
    /*
        Aggregated image sheets are collections of image sheets and behave just like
        one giant image sheet. This class is not exposed to users through documentation
        as it implements the same interface as a normal ImageSheet. These are created by
        the user by passing in a list of sheet names to the ImageSheet.loadFromResources
        functions instead of a single name.
    */
    internal class AggregatedImageSheet : ImageSheet {

        private Dictionary<string, ImageSheet> _sheetsById = new Dictionary<string, ImageSheet>();
        private List<ImageSheet> _orderedSheets;
        private  List<string> _ids = new List<string>();

        private bool _isLoaded = false;

        constructor(List<BasicImageSheet> sheets) : base() {

            this._orderedSheets = new List<ImageSheet>() + sheets;

            if (sheets.length == 0) {
                this._isLoaded = true;
            } else {
                for (BasicImageSheet sheet : sheets) {
                    string id = sheet._id;
                    this._sheetsById[id] = sheet;
                    this._ids.add(id);
                    this._weight += sheet._weight;
                }
            }
        }

        public override ImageResource getImage(string resourcePath) {
            ManifestFileInfo res = ImageResourceManifest.getFileInfo(resourcePath, true);
            ImageSheet sheet = this._sheetsById.get(res.sheetId);
            if (sheet == null) {
                // TODO: show the ID's of the loaded ones?
                throw new ImageResources.ImageNotFoundException("Resource '{0}' is not included in this sheet.", resourcePath);
            }

            return sheet.getImage(resourcePath);
        }

        public override bool isDone() {
            if (this._isLoaded) return true;

            for (ImageSheet sheet : this._orderedSheets) {
                if (!sheet.isDone()) {
                    return false;
                }
            }

            this._isLoaded = true;
            return true;
        }

        public override float getProgress() {
            if (this._isLoaded) return 1.0;

            float progress = 0.0;
            for (ImageSheet sheet : this._orderedSheets) {
                progress += sheet.getProgress() * sheet._weight;
            }

            return progress / this._weight;
        }

        public override List<string> getFiles() {
            List<string> output = new List<string>();
            for (ImageSheet sheet : this._orderedSheets) {
                output.concat(sheet.getFiles());
            }
            output.sort();
            return output;
        }
    }
}
