using System;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using ms.aq.cview.util;

namespace ms.aq.cview.query {
    public class FromTable {
        public string Table;
        public string Alias;
    }
    /**
     * Generates and keeps track of what pieces are involved in a query
     */
    public class QueryInfoManager {
        private Hashtable ahs, hmap, ftmap, allD;
        private StringCollection conditions, measureList;
        private ArrayList distinctTables;
        private static StringCollection EMPTY = new StringCollection();
        private SelectionSets sSets;
        private P1QueryFactory qf;
        private table_cube_interface tci;
        public string table;

        public QueryInfoManager(ref Hashtable allhierarchies, ref Hashtable _allDimensions,
            ref SelectionSets ss, string table, table_cube_interface tci) {
            this.tci = tci;
            sSets = ss;
            hmap = TokenCollectionManager.CreateHierarchyMap(ref sSets);
            ahs = allhierarchies;
            allD = _allDimensions;
            measureList = GetReferencedMeasures(hmap);
            ftmap = CreateHierarchy2TableMap(hmap);
            distinctTables = GetDistinctTables(ftmap);
            this.table = table;
            switch (ss.PlotType) {
                case PrefixDecoder.P1: qf = new P1QueryFactory(tci);
                    break;
                default: throw new Exception("unknown plot type");
            }
            
        }
        public StringCollection GetDimensions() {
            StringCollection rst = new StringCollection();
            foreach (object o in hmap.Keys) {
                string h = TokenCollectionManager.GetHierarchyUID(o.ToString());
                string dim = ((VHierarchy)ahs[h]).ParentDimension.UID;
                if (rst.Contains(dim)) continue;
                rst.Add(dim);
            }
            return rst;
        }
        /*
         * hierarchyUID,tableName
         */
        public Hashtable GetHierarchy2TableMap() { return ftmap; }
        public ArrayList GetDistinctTables() { return distinctTables; }
        public SelectionSets GetSelectionSets() { return sSets; }
        public StringCollection GetConditions() { return conditions; }
        public StringCollection GetSelections(object extended) {
            return qf.GetSelections(sSets, ftmap, ahs,extended); 
        }
        public string GetGroupBy() {
            return qf.GetGroupBy(sSets, ftmap, ahs);
        }
        
        /**
         * Creates a hashtable, where each key is a hierarchy, and each 
         * value is sql table that hierarchy maps to.
         * If multiple hierarchies reference the same table then
         * this will put the same table in both references.
         */
        private Hashtable CreateHierarchy2TableMap(Hashtable hmap) {
            Hashtable rst = new Hashtable();
            char alias = 'a';
            bool noadd;
            foreach (object k in hmap.Keys) {
                noadd = false;
                foreach (object v in rst.Values) {//probably a more efficient way to do this...
                    FromTable existing = (FromTable)v;
                    if (existing.Table == table) {
                        noadd = true;
                        rst.Add(k, existing);
                        break;
                    }
                }
                if (noadd) continue;
                FromTable ft = new FromTable();
                ft.Alias = (alias++).ToString();
                ft.Table = table;
                //ft.PKey = ((VHierarchy)ahs[k]).ParentDimension.PKey;
                rst.Add(k, ft);
            }
            return rst;
        }
        /*
        * Creates a list of all Measures referenced by a query 
        * each item is all uppercase.
        */
        private StringCollection GetReferencedMeasures(Hashtable hmap) {
            StringCollection rst = new StringCollection();
            foreach (object o in hmap.Keys) {
//                VHierarchy vh = (VHierarchy)ahs[o];
  //              if (vh.ParentDimension.Type == VDType.MEASURE)
                    rst.Add(o.ToString().ToUpper());
            }
            return rst;
        }
        /**
         * A simple list of all tables referenced in a Hierarchy2Table map.
         */
        private ArrayList GetDistinctTables(Hashtable ftmap) {
            ArrayList rst = new ArrayList();
            foreach (object o in ftmap.Values)
                if (rst.Contains(o))
                    continue;
                else rst.Add(o);
            return rst;
        }
        private ArrayList GetMeasuresTables(Hashtable ftmap) {
            ArrayList rst = new ArrayList();
            foreach (object key in ftmap.Keys) {
                VHierarchy vh = (VHierarchy)ahs[key];
                if (vh.ParentDimension.Type != VDType.MEASURE) continue;
                if (!rst.Contains(ftmap[key])) rst.Add(ftmap[key]);
            }
            return rst;
        }
        private ArrayList GetNonMeasuresTables(Hashtable ftmap) {
            ArrayList rst = new ArrayList();
            foreach (object key in ftmap.Keys) {
                VHierarchy vh = (VHierarchy)ahs[key];
                if (vh.ParentDimension.Type == VDType.MEASURE) continue;
                if (!rst.Contains(ftmap[key])) rst.Add(ftmap[key]);
            }
            return rst;
        }
        private bool isRange(string s) {
            return s.IndexOf(":") > -1;
        }
        private string uid2value(string uid) {
            return common.debracket(common.UID2Tokens(uid)[2]);
        }
        private bool CollectionListContains(ArrayList collectionlist, string token) {
            foreach (object o in collectionlist) {
                StringCollection sc = (StringCollection)o;
                foreach (string s in sc) {
                    if (s == token)
                        return true;
                }
            }
            return false;
        }

        public StringCollection CreateConditions(SelectionSets sSets, Hashtable ahs, Hashtable hmap, Hashtable ftmap,
            ArrayList constraints) {
            StringCollection rst = new StringCollection();
            //ArrayList al = sSets.GetCollectionsByPrefix(constraintPrefix);
            string xx;
            foreach (object k in hmap.Keys) {//referenced hierarchies
                ArrayList la = (ArrayList)hmap[k];
                string hconds = "";
                foreach (object t in la) {//referenced members
                    string token = t.ToString();

                    if (CollectionListContains(constraints, token)) {
                        VHierarchy vh = (VHierarchy)ahs[TokenCollectionManager.GetHierarchyUID(token)];
                        StringCollection s2 = common.UID2Tokens(token);
                        string val = common.debracket(s2[2]);
                        string h = s2[0] + "." + s2[1];
                        FromTable ft = (FromTable)ftmap[h];
                        hconds += "\t\t(" + ft.Alias + "." + tci.Hierachy2Column(h, out xx, ahs) + " = " + common.sqlifyValue(val) + ")";
                        hconds += " OR\n";
                    }
                }
                if (hconds != "") {
                    hconds = hconds.Substring(0, hconds.Length - 4);//trim last 'or' and \n
                    hconds = "\n" + hconds + "\n\t";
                    rst.Add(hconds);
                }
            }
            return rst;
        }
    }

}