//------------------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// Microsoft
//------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Xsl.Qil;
namespace System.Xml.Xsl.Xslt {
    internal class StylesheetLevel {
        public Stylesheet[] Imports = null;
        // If (this is Stylesheet) {
        //   ModeFlags and ApplyFunctions are abblout apply-imports
        // } else {
        //   ModeFlags and ApplyFunctions are abblout apply-templates
        // }
        // mode -> FocusFlags; Used to generate and call apply-imports/apply-template functions
        public Dictionary ModeFlags = new Dictionary();
        // mode -> xsl:apply-import functions for that mode
        public Dictionary> ApplyFunctions = new Dictionary>();
    }
    internal class Stylesheet : StylesheetLevel {
        private Compiler compiler;
        public List ImportHrefs = new List();
        public List        GlobalVarPars       = new List();
        // xsl:attribute-set/@name -> AttributeSet
        public Dictionary        AttributeSets   = new Dictionary();
        private int                importPrecedence;
        private int                orderNumber          = 0;
        /*
            WhitespaceRules[0] - rules with default priority  0
            WhitespaceRules[1] - rules with default priority -0.25
            WhitespaceRules[2] - rules with default priority -0.5
        */        
        public List[]   WhitespaceRules = new List[3];
        public List Templates = new List();  // Templates defined on this level. Empty for RootLevel.
        // xsl:template/@mode -> list of @match'es
        public Dictionary> TemplateMatches = new Dictionary>();
        public void AddTemplateMatch(Template template, QilLoop filter) {
            List matchesForMode;
            if (!TemplateMatches.TryGetValue(template.Mode, out matchesForMode)) {
                matchesForMode = TemplateMatches[template.Mode] = new List();
            }
            matchesForMode.Add(new TemplateMatch(template, filter));
        }
        public void SortTemplateMatches() {
            foreach (QilName mode in TemplateMatches.Keys) {
                TemplateMatches[mode].Sort(TemplateMatch.Comparer);
            }
        }
        public Stylesheet(Compiler compiler, int importPrecedence) {
            this.compiler         = compiler;
            this.importPrecedence = importPrecedence;
            WhitespaceRules[0] = new List();
            WhitespaceRules[1] = new List();
            WhitespaceRules[2] = new List();
        }
        public int ImportPrecedence { get { return importPrecedence; } }
        public void AddWhitespaceRule(int index, WhitespaceRule rule) {
            WhitespaceRules[index].Add(rule);
        }
        public bool AddVarPar(VarPar var) {
            Debug.Assert(var.NodeType == XslNodeType.Variable || var.NodeType == XslNodeType.Param);
            Debug.Assert(var.Name.NamespaceUri != null, "Name must be resolved in XsltLoader");
            foreach (XslNode prevVar in GlobalVarPars) {
                if (prevVar.Name.Equals(var.Name)) {
                    // [ERR XT0630] It is a static error if a stylesheet contains more than one binding
                    // of a global variable with the same name and same import precedence, unless it also
                    // contains another binding with the same name and higher import precedence.
                    return compiler.AllGlobalVarPars.ContainsKey(var.Name);
                }
            }
            GlobalVarPars.Add(var);
            return true;
        }
        public bool AddTemplate(Template template) {
            Debug.Assert(template.ImportPrecedence == 0);
            template.ImportPrecedence = this.importPrecedence;
            template.OrderNumber      = this.orderNumber++;
            compiler.AllTemplates.Add(template);
            if (template.Name != null) {
                Template old;
                if (!compiler.NamedTemplates.TryGetValue(template.Name, out old)) {
                    compiler.NamedTemplates[template.Name] = template;
                } else {
                    Debug.Assert(template.ImportPrecedence <= old.ImportPrecedence, "Global objects are processed in order of decreasing import precedence");
                    if (old.ImportPrecedence == template.ImportPrecedence) {
                        return false;
                    }
                }
            }
            if (template.Match != null) {
                Templates.Add(template);
            }
            return true;
        }
    }
}