text:
pub type wireBRECORD = *mut _wireBRECORD;
pub type wireVARIANT = *mut _wireVARIANT;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARRAYBOUND {
    pub cElements: ::ULONG,
    pub lLbound: ::LONG,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_BSTR {
    pub Size: ::ULONG,
    pub aBstr: *mut ::wireBSTR,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_UNKNOWN {
    pub Size: ::ULONG,
    pub apUnknown: *mut *mut ::IUnknown,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_DISPATCH {
    pub Size: ::ULONG,
    pub apDispatch: *mut *mut IDispatch,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_VARIANT {
    pub Size: ::ULONG,
    pub aVariant: *mut wireVARIANT,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_BRECORD {
    pub Size: ::ULONG,
    pub aRecord: *mut wireBRECORD,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARR_HAVEIID {
    pub Size: ::ULONG,
    pub apUnknown: *mut *mut ::IUnknown,
    pub iid: ::IID,
}

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum SF_TYPE {
    SF_ERROR = ::VT_ERROR as i32,
    SF_I1 = ::VT_I1 as i32,
    SF_I2 = ::VT_I2 as i32,
    SF_I4 = ::VT_I4 as i32,
    SF_I8 = ::VT_I8 as i32,
    SF_BSTR = ::VT_BSTR as i32,
    SF_UNKNOWN = ::VT_UNKNOWN as i32,
    SF_DISPATCH = ::VT_DISPATCH as i32,
    SF_VARIANT = ::VT_VARIANT as i32,
    SF_RECORD = ::VT_RECORD as i32,
    SF_HAVEIID = ::VT_UNKNOWN as i32 | ::VT_RESERVED as i32
}

pub use self::SF_TYPE::*;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARRAYUNION {
    pub sfType: ::ULONG,
    pub u: __MIDL_IOleAutomationTypes_0001,
}

#[cfg(target_arch = "x86_64")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct __MIDL_IOleAutomationTypes_0001 {
    pub data0: u32,
    pub data1: [u32; 6],
}

#[cfg(target_arch = "x86")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct __MIDL_IOleAutomationTypes_0001 {
    pub data0: u32,
    pub data1: [u32; 5],
}

UNION!(__MIDL_IOleAutomationTypes_0001, data0, BstrStr, BstrStr_mut, SAFEARR_BSTR);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, UnknownStr, UnknownStr_mut, SAFEARR_UNKNOWN);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, DispatchStr, DispatchStr_mut, SAFEARR_DISPATCH);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, VariantStr, VariantStr_mut, SAFEARR_VARIANT);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, RecordStr, RecordStr_mut, SAFEARR_BRECORD);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, HaveIidStr, HaveIidStr_mut, SAFEARR_HAVEIID);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, ByteStr, ByteStr_mut, ::BYTE_SIZEDARR);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, WordStr, WordStr_mut, ::WORD_SIZEDARR);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, LongStr, LongStr_mut, ::DWORD_SIZEDARR);
UNION!(__MIDL_IOleAutomationTypes_0001, data0, HyperStr, HyperStr_mut, ::HYPER_SIZEDARR);

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct _wireSAFEARRAY {
    pub cDims: ::USHORT,
    pub fFeatures: ::USHORT,
    pub cbElements: ::ULONG,
    pub cLocks: ::ULONG,
    pub uArrayStructs: SAFEARRAYUNION,
    pub rgsaBound: [SAFEARRAYBOUND; 1],
}

pub type wireSAFEARRAY = *mut _wireSAFEARRAY;
pub type wirePSAFEARRAY = *mut wireSAFEARRAY;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct SAFEARRAY {
    pub cDims: ::USHORT,
    pub fFeatures: ::USHORT,
    pub cbElements: ::ULONG,
    pub cLocks: ::ULONG,
    pub pvData: ::PVOID,
    pub rgsabound: [SAFEARRAYBOUND; 1],
}

pub type LPSAFEARRAY = *mut SAFEARRAY;

pub const FADF_AUTO: ::DWORD = 0x1;
pub const FADF_STATIC: ::DWORD = 0x2;
pub const FADF_EMBEDDED: ::DWORD = 0x4;
pub const FADF_FIXEDSIZE: ::DWORD = 0x10;
pub const FADF_RECORD: ::DWORD = 0x20;
pub const FADF_HAVEIID: ::DWORD = 0x40;
pub const FADF_HAVEVARTYPE: ::DWORD = 0x80;
pub const FADF_BSTR: ::DWORD = 0x100;
pub const FADF_UNKNOWN: ::DWORD = 0x200;
pub const FADF_DISPATCH: ::DWORD = 0x400;
pub const FADF_VARIANT: ::DWORD = 0x800;
pub const FADF_RESERVED: ::DWORD = 0xf008;

#[cfg(target_arch = "x86_64")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct VARIANT {
    pub data0: u64,
    pub data1: u64,
    pub data2: u64,
}

#[cfg(target_arch = "x86")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct VARIANT {
    pub data0: u64,
    pub data1: u32,
    pub data2: u32,
}

UNION!(VARIANT, data0, vt, vt_mut, ::VARTYPE);
UNION!(VARIANT, data1, llVal, llVal_mut, ::LONGLONG);
UNION!(VARIANT, data1, lVal, lVal_mut, ::LONG);
UNION!(VARIANT, data1, bVal, bVal_mut, ::BYTE);
UNION!(VARIANT, data1, iVal, iVal_mut, ::SHORT);
UNION!(VARIANT, data1, fltVal, fltVal_mut, ::FLOAT);
UNION!(VARIANT, data1, dblVal, dblVal_mut, ::DOUBLE);
UNION!(VARIANT, data1, boolVal, boolVal_mut, ::VARIANT_BOOL);
UNION!(VARIANT, data1, scode, scode_mut, ::SCODE);
UNION!(VARIANT, data1, cyVal, cyVal_mut, ::CY);
UNION!(VARIANT, data1, date, date_mut, ::DATE);
UNION!(VARIANT, data1, bstrVal, bstrVal_mut, ::BSTR);
UNION!(VARIANT, data1, punkVal, punkVal_mut, *mut ::IUnknown);
UNION!(VARIANT, data1, pdispVal, pdispVal_mut, *mut IDispatch);
UNION!(VARIANT, data1, parray, parray_mut, *mut SAFEARRAY);
UNION!(VARIANT, data1, pllVal, pllVal_mut, *mut ::LONGLONG);
UNION!(VARIANT, data1, plVal, plVal_mut, *mut ::LONG);
UNION!(VARIANT, data1, pbVal, pbVal_mut, *mut ::BYTE);
UNION!(VARIANT, data1, piVal, piVal_mut, *mut ::SHORT);
UNION!(VARIANT, data1, pfltVal, pfltVal_mut, *mut ::FLOAT);
UNION!(VARIANT, data1, pdblVal, pdblVal_mut, *mut ::DOUBLE);
UNION!(VARIANT, data1, pboolVal, pboolVal_mut, *mut ::VARIANT_BOOL);
UNION!(VARIANT, data1, pscode, pscode_mut, *mut ::SCODE);
UNION!(VARIANT, data1, pcyVal, pcyVal_mut, *mut ::CY);
UNION!(VARIANT, data1, pdate, pdate_mut, *mut ::DATE);
UNION!(VARIANT, data1, pbstrVal, pbstrVal_mut, *mut ::BSTR);
UNION!(VARIANT, data1, ppunkVal, ppunkVal_mut, *mut *mut ::IUnknown);
UNION!(VARIANT, data1, ppdispVal, ppdispVal_mut, *mut *mut IDispatch);
UNION!(VARIANT, data1, pparray, pparray_mut, *mut *mut SAFEARRAY);
UNION!(VARIANT, data1, pvarVal, pvarVal_mut, *mut VARIANT);
UNION!(VARIANT, data1, byref, byref_mut, ::PVOID);
UNION!(VARIANT, data1, cVal, cVal_mut, ::CHAR);
UNION!(VARIANT, data1, uiVal, uiVal_mut, ::USHORT);
UNION!(VARIANT, data1, ulVal, ulVal_mut, ::ULONG);
UNION!(VARIANT, data1, ullVal, ullVal_mut, ::ULONGLONG);
UNION!(VARIANT, data1, intVal, intVal_mut, ::INT);
UNION!(VARIANT, data1, uintVal, uintVal_mut, ::UINT);
UNION!(VARIANT, data1, pdecVal, pdecVal_mut, *mut ::DECIMAL);
UNION!(VARIANT, data1, pcVal, pcVal_mut, *mut ::CHAR);
UNION!(VARIANT, data1, puiVal, puiVal_mut, *mut ::USHORT);
UNION!(VARIANT, data1, pulVal, pulVal_mut, *mut ::ULONG);
UNION!(VARIANT, data1, pullVal, pullVal_mut, *mut ::ULONGLONG);
UNION!(VARIANT, data1, pintVal, pintVal_mut, *mut ::INT);
UNION!(VARIANT, data1, puintVal, puintVal_mut, *mut ::UINT);
UNION!(VARIANT, data1, pvRecord, pvRecord_mut, ::PVOID);
UNION!(VARIANT, data2, pRecInfo, pRecInfo_mut, *mut IRecordInfo);
UNION!(VARIANT, data0, decVal, decVal_mut, ::DECIMAL);

pub type LPVARIANT = *mut VARIANT;
pub type VARIANTARG = VARIANT;
pub type LPVARIANTARG = *mut VARIANT;
pub type REFVARIANT = *const VARIANT;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct _wireBRECORD {
    fFlags: ::ULONG,
    clSize: ::ULONG,
    pRecInfo: *mut IRecordInfo,
    pRecord: *mut ::BYTE,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct _wireVARIANT {
    clSize: ::DWORD,
    rpcReserved: ::DWORD,
    vt: ::USHORT,
    wReserved1: ::USHORT,
    wReserved2: ::USHORT,
    wReserved3: ::USHORT,
    data0: u64,
    data1: u64,
}

UNION!(_wireVARIANT, data0, llVal, llVal_mut, ::LONGLONG);
UNION!(_wireVARIANT, data0, lVal, lVal_mut, ::LONG);
UNION!(_wireVARIANT, data0, bVal, bVal_mut, ::BYTE);
UNION!(_wireVARIANT, data0, iVal, iVal_mut, ::SHORT);
UNION!(_wireVARIANT, data0, fltVal, fltVal_mut, ::FLOAT);
UNION!(_wireVARIANT, data0, dblVal, dblVal_mut, ::DOUBLE);
UNION!(_wireVARIANT, data0, boolVal, boolVal_mut, ::VARIANT_BOOL);
UNION!(_wireVARIANT, data0, scode, scode_mut, ::SCODE);
UNION!(_wireVARIANT, data0, cyVal, cyVal_mut, ::CY);
UNION!(_wireVARIANT, data0, date, date_mut, ::DATE);
UNION!(_wireVARIANT, data0, bstrVal, bstrVal_mut, ::wireBSTR);
UNION!(_wireVARIANT, data0, punkVal, punkVal_mut, *mut ::IUnknown);
UNION!(_wireVARIANT, data0, pdispVal, pdispVal_mut, *mut IDispatch);
UNION!(_wireVARIANT, data0, parray, parray_mut, wirePSAFEARRAY);
UNION!(_wireVARIANT, data0, brecVal, brecVal_mut, wireBRECORD);
UNION!(_wireVARIANT, data0, pllVal, pllVal_mut, *mut ::LONGLONG);
UNION!(_wireVARIANT, data0, plVal, plVal_mut, *mut ::LONG);
UNION!(_wireVARIANT, data0, pbVal, pbVal_mut, *mut ::BYTE);
UNION!(_wireVARIANT, data0, piVal, piVal_mut, *mut ::SHORT);
UNION!(_wireVARIANT, data0, pfltVal, pfltVal_mut, *mut ::FLOAT);
UNION!(_wireVARIANT, data0, pdblVal, pdblVal_mut, *mut ::DOUBLE);
UNION!(_wireVARIANT, data0, pboolVal, pboolVal_mut, *mut ::VARIANT_BOOL);
UNION!(_wireVARIANT, data0, pscode, pscode_mut, *mut ::SCODE);
UNION!(_wireVARIANT, data0, pcyVal, pcyVal_mut, *mut ::CY);
UNION!(_wireVARIANT, data0, pdate, pdate_mut, *mut ::DATE);
UNION!(_wireVARIANT, data0, pbstrVal, pbstrVal_mut, *mut ::wireBSTR);
UNION!(_wireVARIANT, data0, ppunkVal, ppunkVal_mut, *mut *mut ::IUnknown);
UNION!(_wireVARIANT, data0, ppdispVal, ppdispVal_mut, *mut *mut IDispatch);
UNION!(_wireVARIANT, data0, pparray, pparray_mut, *mut wirePSAFEARRAY);
UNION!(_wireVARIANT, data0, pvarVal, pvarVal_mut, *mut wireVARIANT);
UNION!(_wireVARIANT, data0, cVal, cVal_mut, ::CHAR);
UNION!(_wireVARIANT, data0, uiVal, uiVal_mut, ::USHORT);
UNION!(_wireVARIANT, data0, ulVal, ulVal_mut, ::ULONG);
UNION!(_wireVARIANT, data0, ullVal, ullVal_mut, ::ULONGLONG);
UNION!(_wireVARIANT, data0, intVal, intVal_mut, ::INT);
UNION!(_wireVARIANT, data0, uintVal, uintVal_mut, ::UINT);
UNION!(_wireVARIANT, data0, decVal, decVal_mut, ::DECIMAL);
UNION!(_wireVARIANT, data0, pcVal, pcVal_mut, *mut ::CHAR);
UNION!(_wireVARIANT, data0, puiVal, puiVal_mut, *mut ::USHORT);
UNION!(_wireVARIANT, data0, pulVal, pulVal_mut, *mut ::ULONG);
UNION!(_wireVARIANT, data0, pullVal, pullVal_mut, *mut ::ULONGLONG);
UNION!(_wireVARIANT, data0, pintVal, pintVal_mut, *mut ::INT);
UNION!(_wireVARIANT, data0, puintVal, puintVal_mut, *mut ::UINT);
UNION!(_wireVARIANT, data0, pdecVal, pdecVal_mut, *mut ::DECIMAL);

pub type DISPID = ::LONG;
pub type MEMBERID = DISPID;
pub type HREFTYPE = ::DWORD;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum TYPEKIND {
    TKIND_ENUM = 0,
    TKIND_RECORD,
    TKIND_MODULE,
    TKIND_INTERFACE,
    TKIND_DISPATCH,
    TKIND_COCLASS,
    TKIND_ALIAS,
    TKIND_UNION,
    TKIND_MAX,
}

pub use self::TYPEKIND::*;

#[cfg(target_arch = "x86_64")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct TYPEDESC {
    pub data: u64,
    pub vt: ::VARTYPE,
}

#[cfg(target_arch = "x86")]
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct TYPEDESC {
    pub data: u32,
    pub vt: ::VARTYPE,
}

UNION!(TYPEDESC, data, lptdesc, lptdesc_mut, *mut TYPEDESC);
UNION!(TYPEDESC, data, lpadesc, lpadesc_mut, *mut ARRAYDESC);
UNION!(TYPEDESC, data, hreftype, hreftype_mut, HREFTYPE);

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ARRAYDESC {
    pub tdescElem: TYPEDESC,
    pub cDims: ::USHORT,
    pub rgbounds: [SAFEARRAYBOUND; 1],
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct PARAMDESCEX {
    pub cBytes: ::ULONG,
    pub varDefaultValue: VARIANTARG,
}

pub type LPPARAMDESCEX = *mut PARAMDESCEX;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct PARAMDESC {
    pub pparamdescex: LPPARAMDESCEX,
    pub wParamFlags: ::USHORT,
}

pub type LPPARAMDESC = *mut PARAMDESC;

pub const PARAMFLAG_NONE: ::DWORD = 0;
pub const PARAMFLAG_FIN: ::DWORD = 0x1;
pub const PARAMFLAG_FOUT: ::DWORD = 0x2;
pub const PARAMFLAG_FLCID: ::DWORD = 0x4;
pub const PARAMFLAG_FRETVAL: ::DWORD = 0x8;
pub const PARAMFLAG_FOPT: ::DWORD = 0x10;
pub const PARAMFLAG_FHASDEFAULT: ::DWORD = 0x20;
pub const PARAMFLAG_FHASCUSTDATA: ::DWORD = 0x40;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IDLDESC {
    pub dwReserved: ::ULONG_PTR,
    pub wIDLFlags: ::USHORT,
}

pub type LPIDLDESC = *mut IDLDESC;

pub const IDLFLAG_NONE: ::DWORD = PARAMFLAG_NONE;
pub const IDLFLAG_FIN: ::DWORD = PARAMFLAG_FIN;
pub const IDLFLAG_FOUT: ::DWORD = PARAMFLAG_FOUT;
pub const IDLFLAG_FLCID: ::DWORD = PARAMFLAG_FLCID;
pub const IDLFLAG_FRETVAL: ::DWORD = PARAMFLAG_FRETVAL;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ELEMDESC {
    pub tdesc: TYPEDESC,
    pub idldesc: IDLDESC,
}
UNION!(ELEMDESC, idldesc, paramdesc, paramdesc_mut, PARAMDESC);

pub type LPELEMDESC = *mut ELEMDESC;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct TYPEATTR {
    pub guid: ::GUID,
    pub lcid: ::LCID,
    pub dwReserved: ::DWORD,
    pub memidConstructor: ::MEMBERID,
    pub memidDestructor: ::MEMBERID,
    pub lpstrSchema: ::LPOLESTR,
    pub cbSizeInstance: ::ULONG,
    pub typekind: ::TYPEKIND,
    pub cFuncs: ::WORD,
    pub cVars: ::WORD,
    pub cImplTypes: ::WORD,
    pub cbSizeVft: ::WORD,
    pub cbAlignment: ::WORD,
    pub wTypeFlags: ::WORD,
    pub wMajorVerNum: ::WORD,
    pub wMinorVerNum: ::WORD,
    pub tdescAlias: ::TYPEDESC,
    pub idldescType: ::IDLDESC,
}

pub type LPTYPEATTR = *mut TYPEATTR;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct DISPPARAMS {
    pub rgvarg: *mut VARIANTARG,
    pub rgdispidNamedArgs: *mut DISPID,
    pub cArgs: ::UINT,
    pub cNamedArgs: ::UINT,
}

#[repr(C)] #[derive(Copy)]
pub struct EXCEPINFO {
    pub wCode: ::WORD,
    pub wReserved: ::WORD,
    pub bstrSource: ::BSTR,
    pub bstrDescription: ::BSTR,
    pub bstrHelpFile: ::BSTR,
    pub dwHelpContext: ::DWORD,
    pub pvReserved: ::PVOID,
    pub pfnDeferredFillIn: Option<unsafe extern "system" fn(einfo: *mut EXCEPINFO) -> ::HRESULT>,
    pub scode: ::SCODE,
}

impl Clone for EXCEPINFO {
    fn clone(&self) -> Self {
        *self
    }
}

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum CALLCONV {
    CC_FASTCALL = 0,
    CC_CDECL = 1,
    CC_MSCPASCAL,
    CC_PASCAL,
    CC_MACPASCAL,
    CC_STDCALL,
    CC_FPFASTCALL,
    CC_SYSCALL,
    CC_MPWCDECL,
    CC_MPWPASCAL,
    CC_MAX,
}

pub use self::CALLCONV::*;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum FUNCKIND {
    FUNC_VIRTUAL = 0,
    FUNC_PUREVIRTUAL,
    FUNC_NONVIRTUAL,
    FUNC_STATIC,
    FUNC_DISPATCH,
}

pub use self::FUNCKIND::*;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum INVOKEKIND {
    INVOKE_FUNC = 1,
    INVOKE_PROPERTYGET = 2,
    INVOKE_PROPERTYPUT = 4,
    INVOKE_PROPERTYPUTREF = 8,
}

pub use self::INVOKEKIND::*;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct FUNCDESC {
    pub memid: ::MEMBERID,
    pub lprgscode: *mut ::SCODE,
    pub lprgelemdescParam: *mut ::ELEMDESC,
    pub funckind: ::FUNCKIND,
    pub invkind: ::INVOKEKIND,
    pub callconv: ::CALLCONV,
    pub cParams: ::SHORT,
    pub cParamsOpt: ::SHORT,
    pub oVft: ::SHORT,
    pub cScodes: ::SHORT,
    pub elemdescFunc: ::ELEMDESC,
    pub wFuncFlags: ::WORD,
}

pub type LPFUNCDESC = *mut FUNCDESC;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum VARKIND {
    VAR_PERINSTANCE = 0,
    VAR_STATIC,
    VAR_CONST,
    VAR_DISPATCH,
}

pub use self::VARKIND::*;

pub const IMPLTYPEFLAG_FDEFAULT: ::DWORD = 0x1;
pub const IMPLTYPEFLAG_FSOURCE: ::DWORD = 0x2;
pub const IMPLTYPEFLAG_FRESTRICTED: ::DWORD = 0x4;
pub const IMPLTYPEFLAG_FDEFAULTVTABLE: ::DWORD = 0x8;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct VARDESC {
    pub memid: MEMBERID,
    pub lpstrSchema: ::LPOLESTR,
    pub lpvarValue: *mut VARIANT,
    pub elemdescVar: ::ELEMDESC,
    pub wVarFlags: ::WORD,
    pub varkind: VARKIND,
}

UNION!(VARDESC, lpvarValue, oInst, oInst_mut, ::ULONG);

pub type LPVARDESC = *mut VARDESC;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum TYPEFLAGS {
    TYPEFLAG_FAPPOBJECT = 0x1,
    TYPEFLAG_FCANCREATE = 0x2,
    TYPEFLAG_FLICENSED  = 0x4,
    TYPEFLAG_FPREDECLID = 0x8,
    TYPEFLAG_FHIDDEN = 0x10,
    TYPEFLAG_FCONTROL = 0x20,
    TYPEFLAG_FDUAL = 0x40,
    TYPEFLAG_FNONEXTENSIBLE = 0x80,
    TYPEFLAG_FOLEAUTOMATION = 0x100,
    TYPEFLAG_FRESTRICTED = 0x200,
    TYPEFLAG_FAGGREGATABLE = 0x400,
    TYPEFLAG_FREPLACEABLE = 0x800,
    TYPEFLAG_FDISPATCHABLE = 0x1000,
    TYPEFLAG_FREVERSEBIND = 0x2000,
    TYPEFLAG_FPROXY = 0x4000
}

pub use self::TYPEFLAGS::*;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum FUNCFLAGS {
    FUNCFLAG_FRESTRICTED = 0x1,
    FUNCFLAG_FSOURCE = 0x2,
    FUNCFLAG_FBINDABLE = 0x4,
    FUNCFLAG_FREQUESTEDIT = 0x8,
    FUNCFLAG_FDISPLAYBIND = 0x10,
    FUNCFLAG_FDEFAULTBIND = 0x20,
    FUNCFLAG_FHIDDEN = 0x40,
    FUNCFLAG_FUSESGETLASTERROR = 0x80,
    FUNCFLAG_FDEFAULTCOLLELEM = 0x100,
    FUNCFLAG_FUIDEFAULT = 0x200,
    FUNCFLAG_FNONBROWSABLE = 0x400,
    FUNCFLAG_FREPLACEABLE = 0x800,
    FUNCFLAG_FIMMEDIATEBIND = 0x1000
}

pub use self::FUNCFLAGS::*;

#[repr(i32)] #[derive(Copy, Clone, Debug)] #[allow(unused_qualifications)]
pub enum VARFLAGS {
    VARFLAG_FREADONLY = 0x1,
    VARFLAG_FSOURCE = 0x2,
    VARFLAG_FBINDABLE = 0x4,
    VARFLAG_FREQUESTEDIT = 0x8,
    VARFLAG_FDISPLAYBIND = 0x10,
    VARFLAG_FDEFAULTBIND = 0x20,
    VARFLAG_FHIDDEN = 0x40,
    VARFLAG_FRESTRICTED = 0x80,
    VARFLAG_FDEFAULTCOLLELEM = 0x100,
    VARFLAG_FUIDEFAULT = 0x200,
    VARFLAG_FNONBROWSABLE = 0x400,
    VARFLAG_FREPLACEABLE = 0x800,
    VARFLAG_FIMMEDIATEBIND = 0x1000
}

pub use self::VARFLAGS::*;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct CLEANLOCALSTORAGE {
    pub pInterface: *mut ::IUnknown,
    pub pStorage: ::PVOID,
    pub flags: ::DWORD,
}

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct CUSTDATAITEM {
    pub guid: ::GUID,
    pub varValue: VARIANTARG,
}

pub type LPCUSTDATAITEM = *mut CUSTDATAITEM;

#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct CUSTDATA {
    pub cCustData: ::DWORD,
    pub prgCustData: LPCUSTDATAITEM,
}

pub type LPCUSTDATA = *mut CUSTDATA;

pub type LPCREATETYPEINFO = *mut ICreateTypeInfo;

RIDL!(
interface ICreateTypeInfo(ICreateTypeInfoVtbl): IUnknown(IUnknownVtbl) {
    fn SetGuid(&mut self, guid: ::REFGUID) -> ::HRESULT,
    fn SetTypeFlags(&mut self, uTypeFlags: ::UINT) -> ::HRESULT,
    fn SetDocString(&mut self, pStrDoc: ::LPOLESTR) -> ::HRESULT,
    fn SetHelpContext(&mut self, dwHelpContext: ::DWORD) -> ::HRESULT,
    fn SetVersion(&mut self, wMajorVerNum: ::WORD, wMinorVerNum: ::WORD) -> ::HRESULT,
    fn AddRefTypeInfo(&mut self, pTInfo: *mut ITypeInfo) -> ::HRESULT,
    fn AddFuncDesc(&mut self, index: ::UINT, pFuncDesc: *mut FUNCDESC) -> ::HRESULT,
    fn SetImplTypeFlags(&mut self, index: ::UINT, implTypeFlags: ::INT) -> ::HRESULT,
    fn SetAlignment(&mut self, cbAlignment: ::WORD) -> ::HRESULT,
    fn SetSchema(&mut self, pStrSchema: ::LPOLESTR) -> ::HRESULT,
    fn AddVarDesc(&mut self, index: ::UINT, pVarDesc: *mut VARDESC) -> ::HRESULT,
    fn SetFuncAndParamNames(
        &mut self, index: ::UINT, rgszNames: *mut ::LPOLESTR, cNames: ::UINT
    ) -> ::HRESULT,
    fn SetVarName(&mut self, index: ::UINT, szName: ::LPOLESTR) -> ::HRESULT,
    fn SetTypeDescAlias(&mut self, pTDescAlias: *mut TYPEDESC) -> ::HRESULT,
    fn DefineFuncAsDllEntry(
        &mut self, index: ::UINT, szDllName: ::LPOLESTR, szProcName: ::LPOLESTR
    ) -> ::HRESULT,
    fn SetFuncDocString(&mut self, index: ::UINT, szDocString: ::LPOLESTR) -> ::HRESULT,
    fn SetVarDocString(&mut self, index: ::UINT, szDocString: ::LPOLESTR) -> ::HRESULT,
    fn SetFuncHelpContext(&mut self, index: ::UINT, dwHelpContext: ::DWORD) -> ::HRESULT,
    fn SetVarHelpContext(&mut self, index: ::UINT, dwHelpContext: ::DWORD) -> ::HRESULT,
    fn SetMops(&mut self, index: ::UINT, bstrMops: ::BSTR) -> ::HRESULT,
    fn SetTypeIdldesc(&mut self, pIdlDesc: *mut IDLDESC) -> ::HRESULT,
    fn LayOut(&mut self) -> ::HRESULT
}
);

// FIXME: Implement these interfaces
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ICreateTypeInfo2;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ICreateTypeLib;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ICreateTypeLib2;

pub type LPDISPATCH = *mut IDispatch;

pub const DISPID_UNKNOWN: ::INT = -1;
pub const DISPID_VALUE: ::INT = 0;
pub const DISPID_PROPERTYPUT: ::INT = -3;
pub const DISPID_NEWENUM: ::INT = -4;
pub const DISPID_EVALUATE: ::INT = -5;
pub const DISPID_CONSTRUCTOR: ::INT = -6;
pub const DISPID_DESTRUCTOR: ::INT = -7;
pub const DISPID_COLLECT: ::INT = -8;

RIDL!(
interface IDispatch(IDispatchVtbl): IUnknown(IUnknownVtbl) {
    fn GetTypeInfoCount(&mut self, pctinfo: *mut ::UINT) -> ::HRESULT,
    fn GetTypeInfo(
        &mut self, iTInfo: ::UINT, lcid: ::LCID, ppTInfo: *mut *mut ITypeInfo
    ) -> ::HRESULT,
    fn GetIDsOfNames(
        &mut self, riid: ::REFIID, rgszNames: *mut ::LPOLESTR, cNames: ::UINT, lcid: ::LCID,
        rgDispId: *mut ::DISPID
    ) -> ::HRESULT,
    fn Invoke(
        &mut self, dispIdMember: ::DISPID, riid: ::REFIID, lcid: ::LCID, wFlags: ::WORD,
        pDispParams: *mut ::DISPPARAMS, pVarResult: *mut VARIANT, pExcepInfo: *mut ::EXCEPINFO,
        puArgErr: *mut ::UINT
    ) -> ::HRESULT
}
);

// FIXME: Implement these interfaces
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IEnumVARIANT;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeComp;

RIDL!(
interface ITypeInfo(ITypeInfoVtbl): IUnknown(IUnknownVtbl) {
    fn GetTypeAttr(&mut self, ppTypeAttr: *mut *mut TYPEATTR) -> ::HRESULT,
    fn GetTypeComp(&mut self, ppTComp: *mut *mut ITypeComp) -> ::HRESULT,
    fn GetFuncDesc(&mut self, index: ::UINT, ppFunDesc: *mut *mut FUNCDESC) -> ::HRESULT,
    fn GetVarDesc(&mut self, index: ::UINT, pPVarDesc: *mut *mut VARDESC) -> ::HRESULT,
    fn GetNames(
        &mut self, memid: MEMBERID, rgBstrNames: *mut ::BSTR, cMaxNames: ::UINT,
        pcNames: *mut ::UINT
    ) -> ::HRESULT,
    fn GetRefTypeOfImplType(&mut self, index: ::UINT, pRefType: *mut HREFTYPE) -> ::HRESULT,
    fn GetImplTypeFlags(&mut self, index: ::UINT, pImplTypeFlags: *mut ::INT) -> ::HRESULT,
    fn GetIDsOfNames(
        &mut self, rgszNames: *mut ::LPOLESTR, cNames: ::UINT, pMemId: *mut MEMBERID
    ) -> ::HRESULT,
    fn Invoke(
        &mut self, pvInstance: ::PVOID, memid: MEMBERID, wFlags: ::WORD,
        pDispParams: *mut DISPPARAMS, pVarResult: *mut VARIANT, pExcepInfo: *mut EXCEPINFO,
        puArgErr: *mut ::UINT
    ) -> ::HRESULT,
    fn GetDocumentation(
        &mut self, memid: MEMBERID, pBstrName: *mut ::BSTR, pBstrDocString: *mut ::BSTR,
        pdwHelpContext: *mut ::DWORD, pBstrHelpFile: *mut ::BSTR
    ) -> ::HRESULT,
    fn GetDllEntry(
        &mut self, memid: MEMBERID, invKind: ::INVOKEKIND, pBstrDllName: *mut ::BSTR,
        pBstrName: *mut ::BSTR, pwOrdinal: *mut ::WORD
    ) -> ::HRESULT,
    fn GetRefTypeInfo(&mut self, hRefType: HREFTYPE, ppTInfo: *mut *mut ITypeInfo) -> ::HRESULT,
    fn AddressOfMember(
        &mut self, memid: MEMBERID, invKind: ::INVOKEKIND, ppv: *mut ::PVOID
    ) -> ::HRESULT,
    fn CreateInstance(
        &mut self, pUnkOuter: *mut ::IUnknown, riid: ::REFIID, ppvObj: *mut ::PVOID
    ) -> ::HRESULT,
    fn GetMops(&mut self, memid: MEMBERID, pBstrMops: *mut ::BSTR) -> ::HRESULT,
    fn GetContainingTypeLib(
        &mut self, ppTLib: *mut *mut ITypeLib, pIndex: *mut ::UINT
    ) -> ::HRESULT,
    fn ReleaseTypeAttr(&mut self, pTypeAttr: *mut TYPEATTR) -> (),
    fn ReleaseFuncDesc(&mut self, pFuncDesc: *mut FUNCDESC) -> (),
    fn ReleaseVarDesc(&mut self, pVarDesc: *mut VARDESC) -> ()
}
);

// FIXME: Implement these interfaces
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeInfo2;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeLib;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeLib2;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeChangeEvents;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IErrorInfo;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ICreateErrorInfo;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ISupportErrorInfo;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeFactory;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct ITypeMarshal;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IRecordInfo;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IErrorLog;
#[repr(C)] #[derive(Clone, Copy, Debug)]
pub struct IPropertyBag;


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Lecidea achrista f. achrista (Sommerf.) Britzelm.

### Remarks
null

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Groups Data</title>

<link href="<?php echo base_url() ?>css/bootstrap.min.css" rel="stylesheet">


text:
#include "utils.h"
#include <string.h>

/* Set the log level for this call. log level defaults to warning.
   parse the string value of level_name to the appropriate log_level_t enum value
*/
void set_conmon_logs(char *level_name, char *cid_, gboolean syslog_)
{
	cid = cid_;
	use_syslog = syslog_;
	// log_level is initialized as Warning, no need to set anything
	if (level_name == NULL)
		return;
	if (!strcmp(level_name, "error") || !strcmp(level_name, "fatal") || !strcmp(level_name, "panic")) {
		log_level = EXIT_LEVEL;
		return;
	} else if (!strcmp(level_name, "warn") || !strcmp(level_name, "warning")) {
		log_level = WARN_LEVEL;
		return;
	} else if (!strcmp(level_name, "info")) {
		log_level = INFO_LEVEL;
		return;
	} else if (!strcmp(level_name, "debug")) {
		log_level = DEBUG_LEVEL;
		return;
	}
	nexitf("No such log level %s", level_name);
}


text:
#ifndef __UM_PTRACE_GENERIC_H
#define __UM_PTRACE_GENERIC_H

#ifndef __ASSEMBLY__

#include <asm/ptrace-abi.h>
#include <sysdep/ptrace.h>

struct pt_regs {
	struct uml_pt_regs regs;
};

#define arch_has_single_step()	(1)

#define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS }

#define PT_REGS_IP(r) UPT_IP(&(r)->regs)
#define PT_REGS_SP(r) UPT_SP(&(r)->regs)

#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)

#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)

#define instruction_pointer(regs) PT_REGS_IP(regs)

struct task_struct;

extern long subarch_ptrace(struct task_struct *child, long request,
	unsigned long addr, unsigned long data);
extern unsigned long getreg(struct task_struct *child, int regno);
extern int putreg(struct task_struct *child, int regno, unsigned long value);

extern int arch_copy_tls(struct task_struct *new);
extern void clear_flushed_tls(struct task_struct *task);
extern void syscall_trace_enter(struct pt_regs *regs);
extern void syscall_trace_leave(struct pt_regs *regs);

#endif

#endif


text:
public class Exercise_7_16
{
  public static void main(String[] args )
  {
    double[] array = new double[5];
    double total = 0;

    if ( args.length != 5 )
        System.out.println("You need to parse 5 integers through the command line");
    else
    {
        for (int i = 0; i < 5; i++)
        {
          array[i] = Double.parseDouble( args[i]);
        }

        for (double j : array)
            total += j;

        System.out.printf("The Sum Of The Command Line arguments %.1f, %.1f, %.1f, %.1f & %.1f Is %.2f.", array[0], array[1], array[2], array[3], array[4], total);
    }
  }
}


text:
YUI.add('visualizer-nav', function (Y) {
  Y.namespace('Visualizer');

  var TIME_GROUPS = {
    'all': null,
    'year': 'year',
    'qtr': 'quarter',
    'month': 'month',
    'week': 'week',
    'day': 'day',
    'hour': 'hour',
    'min': 'minute'
  };

  var GRANULARITY_OPTIONS = {
    null: {
      def: '90D',
      options: ['2Y', '1Y', '6M', '90D', '30D', '7D', 'Custom']
    },
    'year': {
      def: '5Y',
      options: ['50Y', '20Y', '5Y', '2Y', '1Y', 'Custom']
    },
    'quarter': {
      def: '2Y',
      options: ['5Y', '2Y', '1Y', 'Custom']
    },
    'month': {
      def: '1Y',
      options: ['5Y', '2Y', '1Y', '6M', '3M', '2M', '1M', 'Custom']
    },
    'week': {
      def: '6M',
      options: ['2Y', '1Y', '6M', '12W', '8W', '4W', 'Custom']
    },
    'day': {
      def: '90D',
      options: ['1Y', '6M', '90D', '60D', '30D', '7D', 'Custom']
    },
    'hour': {
      def: '72H',
      options: ['30D', '7D', '72H', '48H', '24H', 'Custom']
    },
    'minute': {
      def: '2H',
      options: ['12H', '6H', '2H', '60MIN', '30MIN', 'Custom']
    }
  };

  function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
  }

  function getGranularityInfo(granularity) {
    var offset = parseInt(granularity, 10);
    var type = granularity.substring(granularity.indexOf(offset.toString()) + offset.toString().length).toLowerCase();

    if (type === 'y') type = 'year';
    if (type === 'q') type = 'quarter';
    if (type === 'm') type = 'month';
    if (type === 'w') type = 'week';
    if (type === 'd') type = 'day';
    if (type === 'h') type = 'hour';
    if (type === 'min') type = 'minute';

    return {
      offset: offset,
      type: type
    };
  }

  // earliest Friday today or in future
  function weekEndDate(o) {
    var d = new Date(o.getTime());
    d.setHours(0); d.setMinutes(0); d.setSeconds(0); d.setMilliseconds(0);
    var wkd = parseInt(Y.Date.format(d, {format:'%w'}), 10);
    return Y.Date.addDays(d, (wkd <= 5) ? (5-wkd) : 6);
  }

  // most recent Saturday today or in past
  function weekStartDate(o) {
    var d = new Date(o.getTime());
    d.setHours(0); d.setMinutes(0); d.setSeconds(0); d.setMilliseconds(0);
    var wkd = parseInt(Y.Date.format(d, {format: '%w'}), 10);
    return Y.Date.addDays(d,  - ((wkd < 6) ? (1+wkd) : 0));
  }

  function offsetDate(d, gran_type, drill_type, amount) {
    var orig_drill_type = drill_type;
    // safe-copy date.
    d = new Date(d.getTime());
    // always truncate to hour.
    d.setMinutes(0); d.setSeconds(0); d.setMilliseconds(0);
    // truncate according to drill_type.
    if (drill_type) {
      var tf = _date_truncators[drill_type];
      if ( !tf )
        throw "Unknown date format type: " + drill_type;
      tf(d);
    } else {
      drill_type = gran_type;
    }
    // then, offset by amount of gran_type units, translated to drill_type units, then converted to millis.
    // the above truncation effectively offsets one drill_type unit, so subtract 1.
    // for example, gran_type 'year' and drill_type 'week' means
    // truncate to the start of this week, then offset by (amount * 52 - 1).
    var offset_mult = _offset_units[gran_type][drill_type];
    var units = -(amount * offset_mult - (orig_drill_type ? 1 : 0));
    return _date_offsetters[drill_type](d, units);
  }

  var _offset_units = {
    year: { year: 1, quarter: 4, month: 12, week: 52, day: 366, hour: 366 * 24, minute: 366 * 24 * 60 },
    quarter: { quarter: 1, month: 4, week: 13, day: 92, hour: 92 * 24, minute: 92 * 24 * 60 },
    month: { month: 1, week: 5, day: 31, hour: 31 * 24, minute: 31 * 24 * 60 },
    week: { week: 1, day: 7, hour: 7 * 24, minute: 7 * 24 * 60 },
    day: { day: 1, hour: 24, minute: 24 * 60 },
    hour: { hour: 1, minute: 60 },
    minute: { minute: 1 }
  };

  var _date_truncators = {
    null: function(n) { },
    year: function(n) { n.setMonth(0); n.setDate(1); n.setHours(0); n.setMinutes(0); },
    quarter: function(n) { n.setMonth(n.getMonth() - (n.getMonth() % 3)); n.setDate(1); n.setHours(0); n.setMinutes(0); },
    month: function(n) { n.setDate(1); n.setHours(0); n.setMinutes(0); },
    day: function(n) { n.setHours(0); n.setMinutes(0); },
    date: function(n) { n.setHours(0); n.setMinutes(0); },
    hour: function(n) { n.setMinutes(0); },
    minute: function(n) { },
    week: function(n) { n.setTime( weekStartDate(n).getTime() ); }
  };

  var _date_offsetters = {
    year: Y.Date.addYears,
    quarter: function(d, a) { return Y.Date.addMonths(d, a * 3); },
    month: Y.Date.addMonths,
    day: Y.Date.addDays,
    date: Y.Date.addDays,
    week: function(d, a) { return Y.Date.addDays(d, a * 7); },
    hour: function(d, a) { return new Date(d.getTime() + (a * 3600 * 1000)); },
    minute: function(d, a) { return new Date(d.getTime() + (a * 60 * 1000)); }
  };

  var Nav = function(DataSource) {
    this.DataSource = DataSource;
    this.config = {
      datasource: null,
      layers: [],
      resultSize: null, // null -> 'all'
      timeGroup: 'day', // null -> 'all'
      granularity: '90D',
      timeFrame: {
        start: null,
        end: null
      },
      display: null, // null -> #
      annotation: null
    };
    this.activeLayerId = null;

    this.Calendars = new Y.Visualizer.Component.Calendars({
      el: '.calendar-grp',
      hidden: 'hidden'
    });

    this.Calendars.init();

    this.Display = new Y.Visualizer.Display('.content-wrapper .content', '.content-wrapper .title');

    var layer = this.addLayer();
    this._selectPage(layer.id);

    this.init();
  };

  Nav.prototype = {
    _updateLayerWidth: function() {
      var width = 0;
      Y.all('.layers .layer').each(function(node) {
        width += parseInt(node.getComputedStyle('width'), 10);
      });

      Y.one('.layers').setStyle('width', width > 0 ? width : 350);
    },

    _slideToLayer: function(id) {
      var idx = 0;
      Y.all('.layers .layer').each(function(node, i) {
        if (node.get('id') === id) {
          idx = i;
        }
      });

      Y.one('.layers').setStyle('margin-left', -350 * idx);
    },

    _updatePageArrows: function() {
      var size = Y.all('.layernav .pages .page').size();

      if (size === 1) {
        Y.one('.layernav .arrowleft').addClass('disabled');
        Y.one('.layernav .arrowright').addClass('disabled');
      } else {
        Y.one('.layernav .arrowleft').removeClass('disabled');
        Y.one('.layernav .arrowright').removeClass('disabled');

        Y.all('.layernav .pages .page').each(function(node, idx) {
          if (node.hasClass('selected') && idx === 0) {
            Y.one('.layernav .arrowleft').addClass('disabled');
          } else if (node.hasClass('selected') && idx === size - 1) {
            Y.one('.layernav .arrowright').addClass('disabled');
          }
        }, this);
      }
    },

    _addPage: function(id) {
      var node = Y.one('.layernav .pages');

      var pageNode = Y.Node.create('<div>').addClass('btn icon page');
      pageNode.setData('layer', id);
      pageNode.on('click', function(e) {
        if (e.currentTarget.hasClass('selected') || e.currentTarget.hasClass('disabled')) return;

        this._selectPage(e.currentTarget.getData('layer'));
      }, this);
      node.append(pageNode);

      if (Y.all('.layernav .pages .page').size() > 1) {
        Y.one('.layernav .delete').removeClass('disabled');
      }
    },

    _removePage: function(id) {
      Y.all('.layernav .pages .page').each(function(node) {
        if (node.getData('layer') === id) {
          node.remove();
        }
      });

      if (Y.all('.layernav .pages .page').size() <= 1) {
        Y.one('.layernav .delete').addClass('disabled');
      }
    },

    _selectPage: function(id) {
      var node = Y.one('.layernav .pages');
      node.all('.page').removeClass('selected');
      node.all('.page').each(function(page) {
        if (page.getData('layer') === id) {
          page.addClass('selected');
        }
      });

      this._updatePageArrows();

      this._slideToLayer(id);
      this.setActiveLayerId(id);
    },

    init: function() {
      // setup layer nav interaction
      Y.all('.layernav .btn.delete').on('click', function(e) {
        if (this.config.layers.length <= 1) return;

        var id = Y.one('.layernav .pages .page.selected').getData('layer');

        var doLoad = false;
        var idx = 0;
        for (var i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];

          if (layer.id === id) {
            doLoad = layer.config.cube ? true : false;
            idx = i;
            break;
          }
        }

        if (idx > 0) idx -= 1;

        this.deleteLayer(id);
        this._selectPage(this.config.layers[idx].id);

        if (doLoad) {
          this.update();
          this.load();
        }
      }, this);

      Y.all('.layernav .btn.add').on('click', function(e) {
        var layer = this.addLayer();
        this._selectPage(layer.id);
      }, this);

      Y.all('.layernav .btn.arrowleft').on('click', function(e) {
        var prevId;
        for (var i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];

          if (layer.id === this.activeLayerId) {
            if (i === 0) return;
            break;
          } else {
            prevId = layer.id;
          }
        }

        this._selectPage(prevId);
      }, this);

      Y.all('.layernav .btn.arrowright').on('click', function(e) {
        var i;
        for (i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];

          if (layer.id === this.activeLayerId) {
            if (i === this.config.layers.length - 1) return;
            break;
          }
        }

        this._selectPage(this.config.layers[i + 1].id);
      }, this);

      // setup Result Size interaction
      Y.all('.size .btn-grp .btn').on('click', function(e) {
        var node = e.currentTarget;

        if (node.hasClass('disabled') || node.hasClass('selected')) return;

        node.get('parentNode').all('.btn').removeClass('selected');
        node.addClass('selected');

        this.config.resultSize = node.getHTML().toLowerCase();
        this.load();
      }, this);

      // setup Time Group interaction
      Y.all('.group .btn-grp .btn').on('click', function(e) {
        var node = e.currentTarget;

        if (node.hasClass('disabled') || node.hasClass('selected')) return;

        node.get('parentNode').all('.btn').removeClass('selected');
        node.addClass('selected');

        var grp = node.getHTML().toLowerCase();

        for (var timeGroup in TIME_GROUPS) {
          if (timeGroup === grp) {
            this.config.timeGroup = TIME_GROUPS[timeGroup];
            break;
          }
        }

        for (var i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];

          this.updateTimeDimension(layer);
        }

        this.updateGranularity();
        this.updateTimeFrame(true);
        this.updateDisplay();
        this.load();
      }, this);

      // setup manual Filter creation
      Y.one('.filters .btn.add').on('click', function(e) {
        var node = e.currentTarget;

        if (node.hasClass('disabled')) return;

        var layer = this.getActiveLayer();

        if (!layer.config.cube) return;

        this.openFilterDialog(node);
      }, this);

      // setup Display interaction
      Y.all('.display .btn-grp .btn').on('click', function(e) {
        var node = e.currentTarget;

        if (node.hasClass('disabled') || node.hasClass('selected')) return;

        node.get('parentNode').all('.btn').removeClass('selected');
        node.addClass('selected');

        this.config.display = node.one('span').getHTML();
        this.load(true);
      }, this);

      // Footer Buttons
      var clipboard = new ZeroClipboard(Y.one('.sidebar .link').getDOMNode(), {
        moviePath: 'libs/ZeroClipboard/ZeroClipboard.swf'
      });

      clipboard.on('dataRequested', Y.bind(function(client, args) {
        var clipText;
        if (args.shiftKey) {
          clipText = window.location.origin + this.DataSource.get('lastUrl');
        } else {
          clipText = window.location.href;
        }

        clipboard.setText(clipText);

        var dialog = new Y.Visualizer.Component.Dialog({
          id: 'link-dialog',
          fields: [{
            type: 'information',
            center: true,
            value: 'Successfully copied' + (args.shiftKey ? ' Cubes Raw Data' : '') + ' URL to clipboard!'
          }],
          cancelButton: false
        });

        Y.later(2000, this, function() {
          dialog.close(true);
        });
      }, this));

      Y.one('.btn.export').on('click', function() {
        var dialog = new Y.Visualizer.Component.Dialog({
          id: 'export-dialog',
          title: 'Export',
          icon: 'images/icon-exporting-18-light.png',
          fields: [{
            type: 'information',
            value: 'Choose export type...'
          }],
          buttons: [{
            label: 'Facts',
            click: Y.bind(function() {
              dialog.close(false);
              this.exportFacts();
            }, this)
          }, {
            label: 'CSV',
            click: Y.bind(function() {
              dialog.close();
              this.exportCSV();
            }, this)
          }]
        });
      }, this);

      Y.one('.btn.save').on('click', function() {
        // TODO
      }, this);

      Y.one('.btn.reset').on('click', function() {
        this.fullReset();
      }, this);

      Y.one('.btn.logout').on('click', function() {
        Y.fire('visualizer:logout');
      }, this);

      Y.one('.fullscreen').on('click', function(e) {
        e.currentTarget.toggleClass('active');

        if (e.currentTarget.hasClass('active')) {
          Y.one('.sidebar').addClass('fullscreen');
        } else {
          Y.one('.sidebar').removeClass('fullscreen');
        }

        // wait transition time before attempting resize
        Y.later(300, this, this.resize);
      }, this);

      Y.on('visualizer:calendar_change', function(d) {
        this.config.timeFrame.start = this.Calendars.start.get('selectedDates')[0];
        this.config.timeFrame.end = this.Calendars.end.get('selectedDates')[0];

        this.updateTimeFrame();
        this.load();
      }, this);

      Y.on('visualizer:drilldown', this.drilldown, this);
      Y.on('visualizer:annotate', this.annotate, this);
    },

    getLayer: function(id) {
      for (var i = 0; i < this.config.layers.length; i++) {
        if (this.config.layers[i].id === id) {
          return this.config.layers[i];
        }
      }

      return null;
    },

    addLayer: function(config, loadCube) {
      var id = generateUUID();

      // create the UI
      var layerNode = Y.Node.create('<div>').addClass('layer').set('id', id);
      Y.one('.sidebar .layers').append(layerNode);

      var cubeNode = Y.Node.create('<div>').addClass('section cube');
      cubeNode.append(Y.Node.create('<div>').addClass('header').setHTML('Topic')); // Cube
      cubeNode.append(Y.Node.create('<div>').addClass('dropdown'));
      layerNode.append(cubeNode);

      var measureNode = Y.Node.create('<div>').addClass('section measure');
      measureNode.append(Y.Node.create('<div>').addClass('header').setHTML('View')); // Measure
      measureNode.append(Y.Node.create('<div>').addClass('dropdown'));
      layerNode.append(measureNode);

      var drilldownNode = Y.Node.create('<div>').addClass('section drilldown');
      drilldownNode.append(Y.Node.create('<div>').addClass('header').setHTML('Group By')); // Drilldown
      drilldownNode.append(Y.Node.create('<div>').addClass('dropdown'));
      layerNode.append(drilldownNode);

      // TODO: Handle filters, time dimension, in new layout
      // var filterNode = Y.Node.create('<div>').addClass('section filters');
      // filterNode.append(Y.Node.create('<div>').addClass('header pretty').setHTML('Filters'));
      // filterNode.append(Y.Node.create('<div>').addClass('filter-grp')
      //   .append(Y.Node.create('<div>').addClass('text').setHTML('N/A')));
      // layerNode.append(filterNode);

      // var timeDimensionNode = Y.Node.create('<div>').addClass('section time-dimension');
      // timeDimensionNode.append(Y.Node.create('<div>').addClass('header pretty').setHTML('Time Dimension'));
      // timeDimensionNode.append(Y.Node.create('<div>').addClass('btn-grp')
      //   .append(Y.Node.create('<div>').addClass('text').setHTML('N/A')));
      // layerNode.append(timeDimensionNode);

      this._addPage(id);
      this._updateLayerWidth();

      var baseDropdownConfig = {
        maxOptions: 20,
        width: 330
      };

      // create the config
      var layer = {
        id: id,
        config: {
          cube: null,
          measure: null,
          drilldown: null,
          filters: null,
          timeDimension: null
        },
        UI: {
          Dropdowns: {
            cube: new Y.Visualizer.Component.DropDown('#' + id + ' .cube .dropdown', Y.merge(baseDropdownConfig, {
              itemClick: Y.bind(function(id, val, prevVal, ignorePrevVal) {
                if (!ignorePrevVal && val === prevVal) return;

                var layer = this.getLayer(id);

                layer.config.cube = val;

                var continueLoad = Y.bind(function() {
                  if (val) {
                    this.populateDropdown('measure', layer);
                    this.populateDropdown('drilldown', layer);
                  } else { // clear
                    this.emptyDropdown('measure', layer);
                    this.emptyDropdown('drilldown', layer);
                  }

                  layer.config.filters = null;

                  this.update(layer);
                  this.load();
                }, this);

                if (val) {
                  this.DataSource.loadCube(val, continueLoad);
                } else {
                  continueLoad();
                }
              }, this, id)
            })),
            measure: new Y.Visualizer.Component.DropDown('#' + id + ' .measure .dropdown', Y.merge(baseDropdownConfig, {
              itemClick: Y.bind(function(id, val, prevVal, ignorePrevVal) {
                if (!ignorePrevVal && val === prevVal) return;

                var layer = this.getLayer(id);

                layer.config.measure = val;

                this.update(layer);
                this.load();
              }, this, id)
            })),
            drilldown: new Y.Visualizer.Component.DropDown('#' + id + ' .drilldown .dropdown', Y.merge(baseDropdownConfig, {
              itemClick: Y.bind(function(id, val, prevVal, ignorePrevVal) {
                if (!ignorePrevVal && val === prevVal) return;

                var layer = this.getLayer(id);

                layer.config.drilldown = val;

                this.update(layer);
                this.load();
              }, this, id)
            }))
          }
        },
        getFilterNames: function() {
          var names = [];

          if (this.config.filters) {
            for (var i = 0; i < this.config.filters.length; i++) {
              var filter = this.config.filters[i];

              if (filter.disabled || filter.invert) continue;

              for (var k = 0; k < filter.info.length; k++) {
                var info = filter.info[k];

                if (names.indexOf(info.dim) === -1) {
                  names.push(info.dim);
                }
              }
            }
          }

          return names;
        },
        addFilter: function(f) {
          if (f) {
            var filter;
            var appendFilter = false;

            if (this.config.filters) {
              for (var i = 0; i < this.config.filters.length; i++) {
                filter = this.config.filters[i];

                appendFilter = false;

                if (filter.invert || filter.disabled) {
                  appendFilter = false;
                } else if (filter.info.length < f.length) {
                  appendFilter = true;

                  for (var k = 0; k < filter.info.length; k++) {
                    var info = filter.info[k];

                    if (info.dim !== f[k].dim) {
                      appendFilter = false;
                      break;
                    }
                  }
                }

                if (appendFilter) {
                  filter.info = filter.info.concat(f.slice(f.length - 1));
                  break;
                }
              }
            }

            if (!appendFilter) {
              filter = {
                disabled: false,
                invert: false,
                info: f
              };

              if (!this.config.filters) {
                this.config.filters = [filter];
              } else {
                this.config.filters.push(filter);
              }
            }
          }
        },
        flipFilters: function() {
          if (this.config.filters) {
            for (var i = 0; i < this.config.filters.length; i++) {
              var filter = this.config.filters[i];
              filter.invert = !filter.invert;
            }
          }

          this.updateFilters(this);
        }
      };

      if (config) {
        this.updateLayer(layer, config, true);
      } else {
        this.populateDropdown('cube', layer);
      }

      this.config.layers.push(layer);

      return layer;
    },

    deleteLayer: function(id) {
      if (this.config.layers.length <= 1) return;

      for (var i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];
        if (layer.id === id) {
          this.config.layers.splice(i, 1);
          break;
        }
      }

      Y.one('.layers').one('#' + id).remove();
      this._removePage(id);
      this._updateLayerWidth();
    },

    updateLayer: function(layer, config, loadCube) {
      for (var opt in config) {
        layer.config[opt] = config[opt];

        if (opt === 'cube') {
          this.populateDropdown(opt, layer, layer.config[opt]);
        }
      }

      if (loadCube && layer.config.cube) {
        this.DataSource.loadCube(layer.config.cube, Y.bind(function() {
          this.populateDropdown('measure', layer, layer.config.measure);
          this.populateDropdown('drilldown', layer, layer.config.drilldown);

          this.updateTimeDimension(layer);
          this.updateFilters(layer);
        }, this));
      } else {
        // this.updateTimeDimension(layer);
        this.updateFilters(layer);
      }
    },

    loadCubes: function() {
      var queue = new Y.AsyncQueue();

      function loadCube(layer, isLastLayer) {
        queue.pause();

        var continueLoad = Y.bind(function() {
          this.populateDropdown('measure', layer, layer.config.measure);
          this.populateDropdown('drilldown', layer, layer.config.drilldown);

          this.updateTimeDimension(layer);
          this.updateFilters(layer);

          queue.run();

          if (isLastLayer) {
            this.update();
            this.load(false, true);
          }
        }, this);

        if (layer.config.cube) {
          this.DataSource.loadCube(layer.config.cube, continueLoad);
        } else {
          continueLoad();
        }
      }

      for (var i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];

        queue.add({
          fn: loadCube,
          context: this,
          args: [layer, i === this.config.layers.length - 1]
        });
      }

      queue.run();
    },

    resetLayer: function(id) {
      var layer = this.getLayer(id);

      layer.UI.Dropdowns.cube.setValue(null);
      layer.config.cube = null;

      this.emptyDropdown('measure', layer);
      this.emptyDropdown('drilldown', layer);
      layer.config.filters = null;

      this.updateFilters(layer);
      this.updateTimeDimension(layer);
    },

    getActiveLayer: function() {
      return this.getLayer(this.activeLayerId);
    },

    setActiveLayerId: function(id) {
      if (id) {
        this.activeLayerId = id;
      } else {
        this.activeLayerId = this.config.layers[0].id;
      }
    },

    emptyDropdown: function(id, layer) {
      var dd = layer.UI.Dropdowns[id];

      if (!dd) return;

      dd.empty();

      layer.config[id] = null;
    },

    populateDropdown: function(id, layer, val) {
      var i, firstVal, valToSet,
          valFound = false,
          options = [],
          dd = layer.UI.Dropdowns[id];

      if (!val) val = dd.getValue();

      if (!dd) return;

      if (id === 'cube' || id === 'drilldown') {
        options.push({ val: null, label: ' ' });
        firstVal = null;
      }

      if (id === 'cube') {
        items = this.DataSource.get('cubes');
      } else if (id === 'measure') {
        items = this.DataSource.getMeasures(layer.config.cube);
      }
      if (id === 'drilldown') {
        var filterNames = layer.getFilterNames();
        items = this.DataSource.getDimensions(layer.config.cube, layer.config.measure, filterNames, filterNames.length > 0);
      }

      // split data into categories
      var categoryData = {};

      for (i = 0; i < items.length; i++) {
        if (Y.Lang.isUndefined(items[i].category) || Y.Lang.isNull(items[i].category)) {
          items[i].category = 'Miscellaneous';
        }

        if (Y.Lang.isUndefined(categoryData[items[i].category]) || Y.Lang.isNull(categoryData[items[i].category])) {
          categoryData[items[i].category] = [];
        }

        categoryData[items[i].category].push(items[i]);
      }

      var sortedCategories = Y.Object.keys(categoryData).sort();

      // add options
      for (i = 0; i < sortedCategories.length; i++) {
        var cat = sortedCategories[i];

        var opts = [];
        for (var k = 0; k < categoryData[cat].length; k++) {
          opts.push({ val: categoryData[cat][k].key, label: categoryData[cat][k].label });

          if (Y.Lang.isUndefined(firstVal)) {
            firstVal = categoryData[cat][k].key;
          }

          if (!valFound && !Y.Lang.isUndefined(val) && !Y.Lang.isNull(val) && val === categoryData[cat][k].key) {
            valFound = true;
            valToSet = categoryData[cat][k].key;
          }
        }

        if (sortedCategories.length > 1) {
          options.push({ val: cat, label: cat, category: true, options: opts });
        } else {
          options = options.concat(opts);
        }
      }

      dd.update(options);

      if (valFound) {
        dd.setValue(valToSet);
      } else {
        dd.setValue(firstVal);
      }

      layer.config[id] = dd.getValue();

      return dd;
    },

    addButton: function(node, type, label, selected) {
      if (!node) return;

      var btn = Y.Node.create('<div>').addClass('btn');

      if (selected) {
        btn.addClass('selected');
      }

      if (type === 'text') {
        btn.addClass('text');
        btn.setHTML(label);
      } else {
        // TODO
      }

      node.append(btn);

      return btn;
    },

    isAtLeastOneCube: function() {
      var atLeastOneCube = false;
      for (i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];
        if (layer.config.cube) {
          atLeastOneCube = true;
          break;
        }
      }

      return atLeastOneCube;
    },

    isAtLeastOneDrilldown: function() {
      var atLeastOneDrilldown = false;
      for (i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];
        if (layer.config.drilldown) {
          atLeastOneDrilldown = true;
          break;
        }
      }

      return atLeastOneDrilldown;
    },

    update: function(layer) {
      if (layer) {
        this.updateTimeDimension(layer);
        this.updateFilters(layer);
      }

      this.updateResultSize();
      this.updateTimeGroup();
      this.updateDisplay();
    },

    updateFilters: function(layer) {
      if (!layer) return;

      var node = Y.one('.filters .filter-grp');

      node.empty();

      function emptyFilters() {
        node.append(Y.Node.create('<div>').addClass('text').setHTML('N/A'));
      }

      function removeClick(e) {
        var parentNode = e.currentTarget.get('parentNode');

        var f = JSON.stringify(parentNode.getData('filter'));
        for (var i = 0; i < layer.config.filters.length; i++) {
          var filter = layer.config.filters[i];

          if (JSON.stringify(filter) === f) {
            layer.config.filters.splice(i, 1);
            break;
          }
        }

        parentNode.remove();

        if (node.all('.filter').size() === 0) {
          emptyFilters();
        }

        this.populateDropdown('drilldown', layer);
        this.load();
      }

      function disableClick(e) {
        if (e.currentTarget.hasClass('disabled')) return;

        e.currentTarget.toggleClass('active');

        var parentNode = e.currentTarget.get('parentNode');
        if (e.currentTarget.hasClass('active')) {
          parentNode.one('.invert').removeClass('disabled');
          parentNode.one('.info').removeClass('disabled');
        } else {
          parentNode.one('.invert').addClass('disabled');
          parentNode.one('.info').addClass('disabled');
        }

        var f = JSON.stringify(parentNode.getData('filter'));
        for (var i = 0; i < layer.config.filters.length; i++) {
          var filter = layer.config.filters[i];

          if (JSON.stringify(filter) === f) {
            filter.disabled = !e.currentTarget.hasClass('active');
            break;
          }
        }

        this.populateDropdown('drilldown', layer);
        this.load();
      }

      function invertClick(e) {
        if (e.currentTarget.hasClass('disabled')) return;

        e.currentTarget.toggleClass('active');

        var parentNode = e.currentTarget.get('parentNode');
        if (e.currentTarget.hasClass('active')) {
          parentNode.one('.info').addClass('inverted');
        } else {
          parentNode.one('.info').removeClass('inverted');
        }

        var f = JSON.stringify(parentNode.getData('filter'));
        for (var i = 0; i < layer.config.filters.length; i++) {
          var filter = layer.config.filters[i];

          if (JSON.stringify(filter) === f) {
            filter.invert = e.currentTarget.hasClass('active');
            break;
          }
        }

        this.populateDropdown('drilldown', layer);
        this.load();
      }

      if (layer.config.filters && layer.config.filters.length > 0) {
        for (var i = 0; i < layer.config.filters.length; i++) {
          var filter = layer.config.filters[i];

          var filterNode = Y.Node.create('<div>').addClass('filter');
          filterNode.setData('filter', filter);
          node.append(filterNode);

          var removeNode = Y.Node.create('<div>').addClass('btn icon remove');
          removeNode.on('click', removeClick, this);
          filterNode.append(removeNode);

          var disabledNode = Y.Node.create('<div>').addClass('checkbox');
          disabledNode.on('click', disableClick, this);
          filterNode.append(disabledNode);

          var invertNode = Y.Node.create('<div>').addClass('text invert');
          invertNode.on('click', invertClick, this);
          filterNode.append(invertNode);

          var infoNode = Y.Node.create('<div>').addClass('info');
          filterNode.append(infoNode);

          if (filter.disabled) {
            invertNode.addClass('disabled');
            infoNode.addClass('disabled');
          } else {
            disabledNode.addClass('active');
          }

          if (filter.invert) {
            invertNode.addClass('active');
            infoNode.addClass('inverted');
          }

          for (var k = 0; k < filter.info.length; k++) {
            var info = filter.info[k];

            if (k > 0) {
              infoNode.append(Y.Node.create('<span>').addClass('text').setHTML(':'));
            }

            infoNode.append(Y.Node.create('<span>').addClass('text').setHTML(this.DataSource.getDisplayName(layer.config.cube, info.dim)));
            infoNode.append(Y.Node.create('<span>').addClass('text').setHTML('='));
            infoNode.append(Y.Node.create('<span>').addClass('text').setHTML(info.label || info.val));
          }
        }
      } else {
        emptyFilters();
      }
    },

    updateTimeDimension: function(layer) {
      if (!layer) return;

      var node = Y.one('.time-dimension .btn-grp');

      var selected;
      try {
        selected = node.one('.selected').getData('val');
      } catch(e) {}

      node.empty();

      function emptyTimeDimension() {
        node.append(Y.Node.create('<div>').addClass('text').setHTML('N/A'));
        layer.config.timeDimension = null;
      }

      function btnClick(e) {
        var btnNode = e.currentTarget;

        if (btnNode.hasClass('disabled') || btnNode.hasClass('selected')) return;

        btnNode.get('parentNode').all('.btn').removeClass('selected');
        btnNode.addClass('selected');

        layer.config.timeDimension = btnNode.getData('val');

        this.updateTimeGroup();
        this.updateDisplay();
        this.load();
      }

      if (!layer.config.cube) {
        emptyTimeDimension();
      } else {
        var btns = [];
        var dims = this.DataSource.getDateDimensionsInfo(layer.config.cube);

        if (dims) {
          for (var i = 0; i < dims.length; i++) {
            var btn = this.addButton(node, 'text', dims[i].label, selected === dims[i].val || layer.config.timeDimension === dims[i].val);
            btn.setData('val', dims[i].val);
            btn.on('click', btnClick, this);

            btns.push(btn);
          }
        }

        if (btns.length === 0) {
          emptyTimeDimension();
        } else if (!node.one('.selected')) {
          btns[0].addClass('selected');
          layer.config.timeDimension = node.one('.selected').getData('val');
        }
      }
    },

    updateResultSize: function() {
      var node = Y.one('.size .btn-grp');

      var disabledSizes = [];
      for (var i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];

        if (layer.config.drilldown && this.DataSource.isHighCardinality(layer.config.cube, layer.config.drilldown, null, layer.getFilterNames())) {
          disabledSizes.push('all');
          break;
        }
      }

      var atLeastOneDrilldown = this.isAtLeastOneDrilldown();
      if (!atLeastOneDrilldown) {
        disabledSizes.push('top', 'bottom');
      }

      var atLeastOneCube = this.isAtLeastOneCube();

      node.all('.btn').each(function(btn) {
        var resultSize = btn.getHTML().toLowerCase();

        if (this.config.resultSize === resultSize) {
          btn.addClass('selected');
        }

        if (disabledSizes.indexOf(resultSize) !== -1 || !atLeastOneCube) {
          btn.addClass('disabled');
        } else {
          btn.removeClass('disabled');
        }
      }, this);

      var selected = node.one('.selected');
      if (!selected || selected.hasClass('disabled')) {
        try { selected.removeClass('selected'); } catch(e) {}
        try { node.one('.btn:not(.disabled)').addClass('selected'); } catch(e) {}
      }

      this.config.resultSize = node.one('.selected') ? node.one('.selected').getHTML().toLowerCase() : null;
    },

    updateTimeGroup: function() {
      var node = Y.one('.group .btn-grp');

      var atLeastOneCube = this.isAtLeastOneCube();

      node.all('.btn').each(function(btn) {
        var grp = TIME_GROUPS[btn.getHTML().toLowerCase()];

        if (!atLeastOneCube) {
          btn.addClass('disabled');
          return;
        }

        if (this.config.timeGroup === grp) {
          btn.addClass('selected');
        } else {
          btn.removeClass('selected');
        }

        if (grp === null) {
          btn.removeClass('disabled');
          return;
        }

        for (var i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];

          if (this.DataSource.isValidTimeframe(layer.config.cube, grp, layer.config.timeDimension)) {
            btn.removeClass('disabled');
          } else {
            btn.addClass('disabled');
            return;
          }
        }
      }, this);

      var selected = node.one('.selected');
      if (!selected || selected.hasClass('disabled')) {
        try { selected.removeClass('selected'); } catch(e) {}
        try { node.one('.btn:not(.disabled)').addClass('selected'); } catch(e) {}
      }

      this.config.timeGroup = node.one('.selected') ? TIME_GROUPS[node.one('.selected').getHTML().toLowerCase()] : null;

      this.updateGranularity();
    },

    updateGranularity: function() {
      var i;
      var node = Y.one('.granularity .btn-grp');

      var selected = node.one('.selected') ? node.one('.selected').getHTML() : null;

      node.empty();

      var gran = GRANULARITY_OPTIONS[this.config.timeGroup];

      function btnClick(e) {
        var btnNode = e.currentTarget;
        var gran = btnNode.getHTML().toLowerCase();

        if (gran !== 'custom' && (btnNode.hasClass('disabled') || btnNode.hasClass('selected'))) return;

        btnNode.get('parentNode').all('.btn').removeClass('selected');
        btnNode.addClass('selected');

        this.config.granularity = gran;

        if (gran === 'custom') {
          var range = this.DataSource.getDateRange(this.getActiveLayer().config.cube);
          this.Calendars.toggleVisibility(null, btnNode, this.config.timeGroup, this.config.timeFrame, range[0], range[1]);
          this.updateTimeFrame(true);
        } else {
          this.updateTimeFrame();
          this.load();
        }
      }

      var atLeastOneCube = this.isAtLeastOneCube();

      var btns = [];
      for (i = 0; i < gran.options.length; i++) {
        var opt = gran.options[i];

        var btn = this.addButton(node, 'text', opt, this.config.granularity === opt.toLowerCase());
        if (opt.toLowerCase() === 'custom') btn.addClass('calendar-btn');
        btn.on('click', btnClick, this);

        if (!atLeastOneCube) {
          btn.addClass('disabled');
        } else if (opt.toLowerCase() !== 'custom') {
          var granInfo = getGranularityInfo(opt);
          var dateRange = this.DataSource.getDateRange(this.getActiveLayer().config.cube);
          var startDate = offsetDate(dateRange[1], granInfo.type, this.config.timeGroup, granInfo.offset);

          if (startDate < dateRange[0]) {
            btn.addClass('disabled');
          }
        }

        btns.push(btn);
      }

      if (!node.one('.selected')) {
        node.all('.btn').each(function(btn) {
          if (btn.getHTML() === gran.def) {
            btn.addClass('selected');
          }
        }, this);
      }

      selected = node.one('.selected');
      if (!selected || selected.hasClass('disabled')) {
        try { selected.removeClass('selected'); } catch(e) {}
        try { node.one('.btn:not(.disabled)').addClass('selected'); } catch(e) {}
      }

      this.config.granularity = node.one('.selected') ? node.one('.selected').getHTML().toLowerCase() : null;
      this.updateTimeFrame();
    },

    updateTimeFrame: function(constrainCustom) {
      var node = Y.one('.timeframe');

      if (this.config.granularity === 'custom') {
        if (constrainCustom) {
          this.Calendars.constrainDates(this.config.timeGroup);
          this.config.timeFrame.start = this.Calendars.start.get('selectedDates')[0];
          this.config.timeFrame.end = this.Calendars.end.get('selectedDates')[0];
        }
      } else if (this.config.granularity) {
        var granInfo = getGranularityInfo(this.config.granularity);
        var endDate = this.DataSource.getDateRange(this.getActiveLayer().config.cube)[1];
        var startDate = offsetDate(endDate, granInfo.type, this.config.timeGroup, granInfo.offset);
        this.config.timeFrame.start = startDate;
        this.config.timeFrame.end = endDate;
      } else {
        this.config.timeFrame.start = null;
        this.config.timeFrame.end = null;
      }

      node.one('.start').setHTML(this.config.timeFrame.start ? Y.Date.format(this.config.timeFrame.start, { format: '%b %d, %Y' }) : 'N/A');
      node.one('.end').setHTML(this.config.timeFrame.end ? Y.Date.format(this.config.timeFrame.end, { format: '%b %d, %Y' }) : 'N/A');
    },

    updateDisplay: function() {
      var node = Y.one('.display .btn-grp');

      var atLeastOneCube = false,
          atLeastOnePercentageMeasure = false,
          atLeastOneDrilldown = false,
          atLeastOneFullyNonadditive = false;
      for (var i = 0; i < this.config.layers.length; i++) {
        var layer = this.config.layers[i];

        if (layer.config.cube) {
          atLeastOneCube = true;
        }

        if (this.DataSource.getMeasurementType(layer.config.cube, layer.config.measure) === 'percent') {
          atLeastOnePercentageMeasure = true;
        }

        if (layer.config.drilldown) {
          atLeastOneDrilldown = true;
        }

        if (this.DataSource.isFullyNonadditive(layer.config.cube, layer.config.measure, layer.config.drilldown)) {
          atLeastOneFullyNonadditive = true;
        }
      }

      var disabledDisplays = [];

      if (!atLeastOneCube) {
        if (disabledDisplays.indexOf('text') === -1) disabledDisplays.push('text');
        if (disabledDisplays.indexOf('table') === -1) disabledDisplays.push('table');
      }

      if (atLeastOnePercentageMeasure || atLeastOneFullyNonadditive) {
        if (disabledDisplays.indexOf('pie') === -1) disabledDisplays.push('pie');
        if (disabledDisplays.indexOf('donut') === -1) disabledDisplays.push('donut');
        if (disabledDisplays.indexOf('stacked') === -1) disabledDisplays.push('stacked');
        if (disabledDisplays.indexOf('expanded') === -1) disabledDisplays.push('expanded');
        if (disabledDisplays.indexOf('stream') === -1) disabledDisplays.push('stream');
      }

      if (!atLeastOneDrilldown) {
        if (disabledDisplays.indexOf('bar') === -1) disabledDisplays.push('bar');
        if (disabledDisplays.indexOf('pie') === -1) disabledDisplays.push('pie');
        if (disabledDisplays.indexOf('donut') === -1) disabledDisplays.push('donut');
        if (disabledDisplays.indexOf('expanded') === -1) disabledDisplays.push('expanded');
      } else {
        if (disabledDisplays.indexOf('text') === -1) disabledDisplays.push('text');
      }

      if (!this.config.timeGroup) {
        if (disabledDisplays.indexOf('line') === -1) disabledDisplays.push('line');
        if (disabledDisplays.indexOf('index') === -1) disabledDisplays.push('index');
        if (disabledDisplays.indexOf('stacked') === -1) disabledDisplays.push('stacked');
        if (disabledDisplays.indexOf('expanded') === -1) disabledDisplays.push('expanded');
        if (disabledDisplays.indexOf('stream') === -1) disabledDisplays.push('stream');
        if (disabledDisplays.indexOf('heatmap') === -1) disabledDisplays.push('heatmap');
      } else {
        if (disabledDisplays.indexOf('text') === -1) disabledDisplays.push('text');
        if (disabledDisplays.indexOf('bar') === -1) disabledDisplays.push('bar');
        if (disabledDisplays.indexOf('pie') === -1) disabledDisplays.push('pie');
        if (disabledDisplays.indexOf('donut') === -1) disabledDisplays.push('donut');
      }

      if (!this.config.timeGroup && !atLeastOneDrilldown) {
        if (disabledDisplays.indexOf('table') === -1) disabledDisplays.push('table');
      }

      node.all('.btn').each(function(btn) {
        var type = btn.one('span').getHTML();

        if (type === this.config.display) {
          btn.addClass('selected');
        }

        if (disabledDisplays.indexOf(type) !== -1) {
          btn.addClass('disabled');
        } else {
          btn.removeClass('disabled');
        }
      }, this);

      var selected = node.one('.selected');
      if (!selected || selected.hasClass('disabled')) {
        try { selected.removeClass('selected'); } catch(e) {}
        try { node.one('.btn:not(.disabled)').addClass('selected'); } catch(e) {}
      }

      this.config.display = node.one('.selected span') ? node.one('.selected span').getHTML() : null;
    },

    drilldown: function(d) {
      var layer = this.getActiveLayer();

      if (!d || !layer || !layer.config.drilldown) return;

      var data = d.data.raw ? d.data.raw : d.data;
      var key;

      if (layer.config.drilldown === this.DataSource.getSplitDimensionString()) {
        var withinSplit;

        for (key in data) {
          if (key === layer.config.drilldown) {
            withinSplit = data[key];
          }
        }

        if (!Y.Lang.isUndefined(withinSplit) && !Y.Lang.isNull(withinSplit)) {
          if (!withinSplit && layer.config.filters) {
            layer.config.flipFilters();
          }
        }

        this.populateDropdown('drilldown', layer);
        layer.UI.Dropdowns.drilldown.setValue(null);
        layer.UI.Dropdowns.drilldown.simulateClick(true);
      } else {
        var drillLevelInfo = this.DataSource.getDrillLevelInfo(layer.config.cube, layer.config.drilldown);

        if (drillLevelInfo) {
          var info = [];
          for (var i = 0; i < drillLevelInfo.levels.length; i++) {
            var level = drillLevelInfo.levels[i];

            var levelKey = level.key ? level.key : (level.name ? level.name : level.dim);
            for (key in data) {
              if (key.replace(':', '.') === levelKey.replace(':', '.')) { //(level.name ? level.name.replace(':', '.') : level.dim.replace(':', '.'))) {
                info.push({
                  dim: level.name ? level.name : level.dim,
                  val: data[key] === null ? this.DataSource.getNullString() : data[key],
                  label: level.labelKey ? (level.key === level.labelKey ? null : (data[level.labelKey] === null ? this.DataSource.getNullString() : data[level.labelKey])) : null
                });
              }
            }
          }

          if (info.length > 0) {
            layer.addFilter(info);

            this.populateDropdown('drilldown', layer);
            layer.UI.Dropdowns.drilldown.setValue(!drillLevelInfo.isLastLevel ? drillLevelInfo.nextLevel : null);
            layer.UI.Dropdowns.drilldown.simulateClick(true);
          }
        }
      }
    },

    annotate: function(cfg) {
      if (Y.Lang.isUndefined(cfg)) cfg = null;

      if (cfg && cfg.bbox) {
        cfg.bbox[0] = new Date(cfg.bbox[0]).getTime();
        cfg.bbox[2] = new Date(cfg.bbox[2]).getTime();
      }

      this.config.annotation = Y.Lang.isUndefined(cfg) ? null : cfg;

      Y.fire('visualizer:annotate:update');
    },

    openFilterDialog: function(node) {
      var layer = this.getActiveLayer();
      var filterNames = layer.getFilterNames();

      var dialog;
      var filterInfo = [];

      var oldDialog = Y.one('#create-filter-dialog');
      if (oldDialog) {
        oldDialog.remove(true);
      }

      function updateInfo(g, v, l) {
        var found = false;
        for (var i = 0; i < filterInfo.length; i++) {
          if (filterInfo[i].dim === g) {
            filterInfo[i].val = v;
            filterInfo[i].label = l;
            found = true;
            break;
          }
        }

        if (!found) {
          filterInfo.push({
            dim: g,
            val: v,
            label: l
          });
        }
      }

      function removeInfo(g) {
        for (var i = 0; i < filterInfo.length; i++) {
          if (filterInfo[i].dim === g) {
            filterInfo = filterInfo.slice(0, i);
            break;
          }
        }
      }

      function getGroupNames() {
        var groupNames = [];
        for (var i = 0; i < filterInfo.length; i++) {
          groupNames.push(filterInfo[i].dim);
        }

        return groupNames;
      }

      function mergeFilters(filters, f, parentDims, returnFilterInfo) {
        filters = Y.clone(filters);

        var filter;
        var appendFilter = false;

        if (filters) {
          for (var i = 0; i < filters.length; i++) {
            filter = filters[i];

            appendFilter = false;

            if (!filter.invert && !filter.disabled) {
              appendFilter = true;

              for (var k = 0; k < filter.info.length; k++) {
                var info = filter.info[k];

                if (parentDims.indexOf(info.dim) === -1) {
                  appendFilter = false;
                  break;
                }
              }
            }

            if (appendFilter) {
              filter.info = filter.info.concat(f);
              if (returnFilterInfo) return filter.info;
              break;
            }
          }
        }

        if (!appendFilter) {
          filter = {
            disabled: false,
            invert: false,
            info: f
          };

          if (!filters) {
            filters = [filter];
          } else {
            filters.push(filter);
          }

          if (returnFilterInfo) return f;
        }

        return filters;
      }

      var buildFilterGroup = Y.bind(function(idx, nextLevel) {
        if (!idx) idx = 0;

        var groupItems = [];
        if (idx === 0) {
          var items = this.DataSource.getDimensions(layer.config.cube, layer.config.measure, filterNames.concat(getGroupNames()));

          for (var i = 0; i < items.length; i++) {
            if (!items[i].topLevel) continue;

            groupItems.push({
              value: items[i].key,
              label: items[i].label
            });
          }
        } else {
          groupItems.push({
            value: nextLevel,
            label: this.DataSource.getDisplayName(layer.config.cube, nextLevel)
          });
        }

        var field = {
          id: 'filter-grp_' + idx,
          type: 'dropdown',
          width: 200,
          label: 'Filter By',
          values: groupItems,
          on: {
            change: Y.bind(function(grp, grpLabel, prevGrp) {
              dialog.removeFields('filter-grp_' + idx, 'after');
              if (prevGrp) removeInfo(prevGrp);

              if (!grp) return;

              var highCardinality = this.DataSource.isHighCardinality(layer.config.cube, grp, null, filterNames.concat(getGroupNames()));
              var drillLevelInfo = this.DataSource.getDrillLevelInfo(layer.config.cube, grp);

              if (!highCardinality) {
                dialog.setLoadingState(true);

                var parentDims = [];
                if (drillLevelInfo) {
                  for (var i = 0; i < drillLevelInfo.levels.length - 1; i++) {
                    parentDims.push(drillLevelInfo.levels[i].key.replace('.', ':'));
                  }
                }
                var mergedFilters = mergeFilters(layer.config.filters, filterInfo, parentDims);

                this.DataSource.queryMembers(layer.config.cube, grp, mergedFilters, Y.bind(function(data) {
                  data = data.data;

                  var drillInfo = this.DataSource.getDrillInfo(layer.config.cube, grp);

                  var items = [];
                  var sortNumbers = true;
                  var duplicateLabelMap = {};
                  var i;
                  for (i = 0; i < data.length; i++) {
                    var valueKey = drillInfo.keys[drillInfo.keys.length - 1];
                    var key = data[i][valueKey];
                    var label = data[i][drillInfo.labels[drillInfo.labels.length - 1]];

                    if (typeof label !== 'number') {
                      sortNumbers = false;
                    }

                    items.push({
                      value: key,
                      valueKey: valueKey,
                      label: label,
                      trueLabel: label
                    });
                  }

                  for (i = 0; i < items.length; i++) {
                    var found = false;
                    for (k = i + 1; k < items.length; k++) {
                      if (items[k].label === items[i].label) {
                        found = true;
                        items[k].label = items[k].label + ' (' + items[k].valueKey + ': ' + items[k].value + ')';
                        duplicateLabelMap[items[k].label] = items[k].trueLabel;
                      }
                    }
                    if (found) {
                      items[i].label = items[i].label + ' (' + items[i].valueKey + ': ' + items[i].value + ')';
                      duplicateLabelMap[items[i].label] = items[i].trueLabel;
                    }
                  }

                  if (sortNumbers) {
                    items.sort(function(a, b) {
                      return a.label - b.label;
                    });
                  } else {
                    items.sort(function(a, b) {
                      if ((a.label ? a.label.toLowerCase() : '') < (b.label ? b.label.toLowerCase() : '')) return -1;
                      if ((a.label ? a.label.toLowerCase() : '') > (b.label ? b.label.toLowerCase() : '')) return 1;
                      return 0;
                    });
                  }

                  updateInfo(grp, items[0].value, items[0].trueLabel);

                  var field = {
                    id: 'filter-value_' + idx,
                    type: 'dropdown',
                    width: 200,
                    allowEmpty: false,
                    label: 'Value',
                    values: items,
                    on: {
                      change: function(val, valLabel) {
                        removeInfo(grp);
                        updateInfo(grp, val, duplicateLabelMap[valLabel] ? duplicateLabelMap[valLabel] : valLabel);

                        var nextGrpField = dialog.getField('filter-grp_' + (idx + 1));
                        if (nextGrpField) {
                          dialog.updateFieldValue('filter-grp_' + (idx + 1), null);
                          dialog.removeFields('filter-grp_' + (idx + 1), 'after');
                        }
                      }
                    }
                  };

                  if (dialog.getField('filter-value_' + idx)) {
                    dialog.replaceField('filter-value_' + idx, field);
                  } else {
                    dialog.addField(field, 'filter-grp_' + idx, 'after');
                  }

                  if (drillLevelInfo && drillLevelInfo.nextLevel && !drillLevelInfo.isLastLevel) {
                    dialog.addField(buildFilterGroup(idx + 1, drillLevelInfo.nextLevel));
                  }

                  dialog.setLoadingState(false);
                }, this), function() {
                  // TODO: Handle failure
                  dialog.setLoadingState(false);
                });
              } else { // high cardinality
                var field = {
                  id: 'filter-value_' + idx,
                  type: 'text',
                  width: 200,
                  label: 'Value',
                  on: {
                    change: function(val) {
                      removeInfo(grp);
                      updateInfo(grp, val);

                      var nextGrpField = dialog.getField('filter-grp_' + (idx + 1));
                      if (nextGrpField) {
                        dialog.updateFieldValue('filter-grp_' + (idx + 1), null);
                        dialog.removeFields('filter-grp_' + (idx + 1), 'after');
                      }
                    }
                  }
                };

                if (dialog.getField('filter-value_' + idx)) {
                  dialog.replaceField('filter-value_' + idx, field);
                } else {
                  dialog.addField(field, 'filter-grp_' + idx, 'after');
                }

                if (drillLevelInfo && drillLevelInfo.nextLevel && !drillLevelInfo.isLastLevel) {
                  dialog.addField(buildFilterGroup(idx + 1, drillLevelInfo.nextLevel));
                }
              }
            }, this)
          }
        };

        return [field];
      }, this);

      dialog = new Y.Visualizer.Component.Dialog({
        id: 'create-filter-dialog',
        parent: node.get('parentNode').get('parentNode'),
        modal: false,
        flyout: 'right',
        fields: [
          buildFilterGroup()
        ],
        buttons: [{
          label: 'Create',
          click: Y.bind(function() {
            var i;

            if (filterInfo && filterInfo.length > 0) {
              // fix for hierarchy dimensions
              for (i = 0; i < filterInfo.length; i++) {
                var dim = filterInfo[i].dim;
                if (dim.indexOf('@') !== -1) {
                  if (dim.indexOf(':') !== -1) {
                    filterInfo[i].dim = dim.replace(dim.substring(dim.indexOf('@'), dim.indexOf(':')), '');
                  } else {
                    filterInfo[i].dim = dim.substring(0, dim.indexOf('@'));
                  }
                }
              }

              var drillLevelInfo = this.DataSource.getDrillLevelInfo(layer.config.cube, filterInfo[filterInfo.length - 1].dim);

              var parentDims = [];
              if (drillLevelInfo) {
                for (i = 0; i < drillLevelInfo.levels.length - 1; i++) {
                  parentDims.push(drillLevelInfo.levels[i].key.replace('.', ':'));
                }
              }
              var mergedFilterInfo = mergeFilters(layer.config.filters, filterInfo, parentDims, true);

              layer.addFilter(mergedFilterInfo);

              this.populateDropdown('drilldown', layer);
              layer.UI.Dropdowns.drilldown.setValue(drillLevelInfo && drillLevelInfo.nextLevel && !drillLevelInfo.isLastLevel ? drillLevelInfo.nextLevel : null);
              layer.UI.Dropdowns.drilldown.simulateClick(true);
            }

            dialog.close();
          }, this)
        }]
      });
    },

    exportFacts: function() {
      var layer = this.getActiveLayer();

      if (!layer || !layer.config.cube) return;

      var i;
      var fields = this.DataSource.getFields(layer.config.cube);

      var cols = {};

      for (i = 0; i < fields.length; i++) {
        var checked;

        if (fields[i].type === 'measure') {
          checked = true;
        } else if (layer.config.drilldown) {
          if ((fields[i].type === 'dimension' || fields[i].type === 'level') && (layer.config.drilldown.replace(':', '.') === fields[i].key.replace(':', '.')) ||
            (fields[i].type === 'attribute' && layer.config.drilldown.replace(':', '.') === fields[i].parent.replace(':', '.')))
          {
            checked = true;
          } else {
            checked = false;
          }
        } else {
          checked = false;
        }

        var cbValue = {
          checked: checked,
          value: fields[i].key,
          label: fields[i].label
        };

        if (fields[i].type === 'detail') {
          if (cols['details']) {
            cols['details'].values.push(cbValue);
          } else {
            cols['details'] = {
              id: 'details-cb-grp',
              type: 'checkbox-group',
              inline: false,
              styles: { verticalAlign: 'top' },
              label: 'Details',
              sortIndex: 0,
              values: [cbValue]
            };
          }
        } else if (fields[i].type === 'measure') {
          if (cols['measures']) {
            cols['measures'].values.push(cbValue);
          } else {
            cols['measures'] = {
              id: 'measures-cb-grp',
              type: 'checkbox-group',
              inline: false,
              styles: { verticalAlign: 'top' },
              label: 'Measures',
              sortIndex: 1,
              values: [cbValue]
            };
          }
        } else if (fields[i].type === 'date') {
          if (cols['dates']) {
            cols['dates'].values.push(cbValue);
          } else {
            cols['dates'] = {
              id: 'dates-cb-grp',
              type: 'checkbox-group',
              inline: false,
              styles: { verticalAlign: 'top' },
              label: 'Dates',
              sortIndex: 2,
              values: [cbValue]
            };
          }
        } else {
          if (cols['dimensions']) {
            cols['dimensions'].values.push(cbValue);
          } else {
            cols['dimensions'] = {
              id: 'dimensions-cb-grp',
              type: 'checkbox-group',
              inline: false,
              styles: { verticalAlign: 'top' },
              label: 'Dimensions',
              sortIndex: 3,
              values: [cbValue]
            };
          }
        }
      }

      var col;

      function valSort(a, b) {
        if (a.label.toLowerCase() < b.label.toLowerCase()) return -1;
        if (a.label.toLowerCase() > b.label.toLowerCase()) return 1;
        return 0;
      }

      for (col in cols) {
        cols[col].values.sort(valSort);
      }

      var dialogColumns = [];
      for (col in cols) {
        dialogColumns.push(cols[col]);
      }

      dialogColumns.sort(function(a, b) {
        return a.sortIndex - b.sortIndex;
      });

      var dialog = new Y.Visualizer.Component.Dialog({
        id: 'export-facts-dialog',
        title: 'Facts Export',
        icon: 'images/icon-exporting-18-light.png',
        description: 'Export Facts for ' + this.DataSource.getDisplayName(layer.config.cube) + ' into CSV format.',
        fields: [dialogColumns],
        buttons: [{
          label: 'Export',
          inverted: true,
          click: Y.bind(function() {
            function getCheckedFields(id) {
              var checkedFields = [];

              var cbNode = dialog.getField(id);
              if (cbNode) {
                cbNode.all('input').each(function(n) {
                  if (n.get('checked')) {
                    checkedFields.push(n.get('value'));
                  }
                });
              }

              return checkedFields;
            }

            var fields = [];
            fields = fields.concat(getCheckedFields('details-cb-grp'));
            fields = fields.concat(getCheckedFields('measures-cb-grp'));
            fields = fields.concat(getCheckedFields('dates-cb-grp'));
            fields = fields.concat(getCheckedFields('dimensions-cb-grp'));

            if (fields.length > 0) {
              this.DataSource.exportFacts(this.config, layer.config, fields, 'csv');
              dialog.close();
            } else {
              var errorExportDialog = new Y.Visualizer.Component.Dialog({
                id: 'error-export-dialog',
                parent: 'export-facts-dialog',
                icon: 'images/warning-icon-color.png',
                title: 'Export Failed',
                fields: [{
                  type: 'information',
                  center: true,
                  value: 'No fields are selected!'
                }]
              });
            }
          }, this)
        }]
      });
    },

    exportCSV: function() {
      this.DataSource.exportData(this.config, this.getActiveLayer().config, 'csv');
    },

    load: function(ignoreLoad, ignoreURLUpdate) {
      if (!this.config.display) {
        ignoreLoad = true;
      }

      if (!ignoreURLUpdate) {
        this.config.annotation = null;
      }

      Y.fire('visualizer:nav_change', ignoreLoad, ignoreURLUpdate);
    },

    render: function(data, ignoreLoad) {
      if (!ignoreLoad && (!data || (Y.Lang.isArray(data) && data.length === 0))) {
        Y.fire('visualizer:empty_data');
        return;
      }

      if (!this.config.display) {
        this.Display.clear();
      } else {
        this.Display.render(data, this.generateSimpleConfig(), this.DataSource);

        if (this.config.display === 'table') {
          var exportNode = Y.Node.create('<div>').addClass('viz-table-export');
          exportNode.setAttribute('title', 'Export to CSV');
          exportNode.on('click', function() {
            this.exportCSV();
          }, this);

          Y.one('.viz-table').append(exportNode);
        }
      }
    },

    generateSimpleConfig: function() {
      var config = {};

      for (var opt in this.config) {
        if (opt === 'layers') {
          config[opt] = [];

          for (var i = 0; i < this.config.layers.length; i++) {
            var layer = this.config.layers[i];

            config[opt].push(Y.merge({}, layer.config));
          }
        } else {
          config[opt] = this.config[opt];
        }
      }

      return config;
    },

    build: function(config) {
      var updateFirst = true;

      this.reset();

      if (config) {
        for (var opt in config) {
          if (opt !== 'layers') {
            if (opt === 'timeFrame') {
              for (var tfOpt in config[opt]) {
                config[opt][tfOpt] = Y.Date.parse(config[opt][tfOpt]);
              }
              this.Calendars.updateDates(config[opt]);
            }

            this.config[opt] = config[opt];
          }
        }

        if (config.layers) {
          for (var i = 0; i < config.layers.length; i++) {
            var layerConfig = config.layers[i];

            if (i === 0 && this.config.layers[0]) {
              updateFirst = false;
              this.updateLayer(this.config.layers[0], layerConfig);
            } else {
              if (i === 0) updateFirst = false;
              this.addLayer(layerConfig);
            }
          }
        }
      }

      if (!this.config.datasource) {
        this.config.datasource = this.DataSource.get('url');
      }

      if (!this.config.layers || this.config.layers.length === 0) {
        var layer = this.addLayer();
        this._selectPage(layer.id);
      } else {
        if (updateFirst) {
          this.populateDropdown('cube', this.config.layers[0]);
        }

        this._selectPage(this.config.layers[0].id);
      }

      this.loadCubes();
    },

    resize: function() {
      this.Display.resize();
    },

    reset: function() {
      this.config.datasource = null;
      this.config.resultSize = null;
      this.config.timeGroup = 'day';
      this.config.granularity = '90D';
      this.config.timeFrame = {
        start: null,
        end: null
      };
      this.config.display = null;
      this.config.annotation = null;

      if (this.config.layers) {
        var ids = [];
        var activeId;
        for (var i = 0; i < this.config.layers.length; i++) {
          var layer = this.config.layers[i];
          if (i === 0) {
            this.resetLayer(layer.id);
            activeId = layer.id;
          } else {
            ids.push(layer.id);
          }
        }
        if (ids.length > 0) {
          for (var k = 0; k < ids.length; k++) {
            this.deleteLayer(ids[k]);
          }
        }
        if (activeId) {
          this._selectPage(activeId);
        }
      }
    },

    fullReset: function() {
      this.reset();

      this.update();
      this.load();
    },

    get: function(prop) {
      if (Y.Lang.isUndefined(prop) || Y.Lang.isNull(prop)) return;

      return this[prop];
    }
  };

  Y.Visualizer.Nav = Nav;
}, '1.0', {
  requires: ['node', 'querystring', 'router', 'node-event-simulate', 'async-queue', 'datatype-date',
    'visualizer-component-dropdown', 'visualizer-component-calendars',
    'visualizer-display'
  ]
});


text:
from oslo_policy import policy

from cinder.policies import base

MANAGE_POLICY = "volume_extension:hosts"

hosts_policies = [
    policy.DocumentedRuleDefault(
        name=MANAGE_POLICY,
        check_str=base.RULE_ADMIN_API,
        description="List, update or show hosts for a project.",
        operations=[
            {
                'method': 'GET',
                'path': '/os-hosts'
            },
            {
                'method': 'PUT',
                'path': '/os-hosts/{host_name}'
            },
            {
                'method': 'GET',
                'path': '/os-hosts/{host_id}'
            }
        ])
]

def list_rules():
    return hosts_policies