namespace SqlDynamite.Common

open System
open System.Data
open Microsoft.AnalysisServices.AdomdClient

type SsasMetadataFinder() =
    inherit MetadataFinder()

    member this.GetKeywords() =
        ((this._connection :?> WrapperConnection).InnerConnection :?> AdomdConnection).GetSchemaDataSet(AdomdSchemaGuid.Keywords, null)
    
    member this.GetFunctions() =
        ((this._connection :?> WrapperConnection).InnerConnection :?> AdomdConnection).GetSchemaDataSet(AdomdSchemaGuid.Functions, null)
    
    override this.GetDatabaseList (scname:string) : string list =
        let dbs = ((this._connection :?> WrapperConnection).InnerConnection :?> AdomdConnection).GetSchemaDataSet(AdomdSchemaGuid.Catalogs, null).Tables.Item(0)
        let rec loop n acc =
            if n > 0 then
                let item = (dbs.Rows.Item(n - 1).Item(0).ToString()).Trim()
                loop (n - 1) (item :: acc)
            else
                acc
        loop dbs.Rows.Count []

    override this.Compose(tablename:string, fields:DataTable, keys:DataTable, checks:DataTable) : string =
        raise (NotImplementedException())

    override this.GetDefColumns(name:string, objtype:ObjectType) : DataTable list =
        raise (NotImplementedException())

    override this.GetTextColumns(name:string, objtype:ObjectType) : string list =
        let query = 
            match objtype with
            | ObjectType.CUBE ->
                String.Format("SELECT [CUBE_CAPTION], 'CUBE'
                FROM $system.MDSchema_Cubes
                WHERE CUBE_NAME = '{0}'", name)
            | ObjectType.DIMENSION ->
                let parts = name.Split('.')
                let cube = parts.[0]
                let dimension = parts.[1]
                String.Format("SELECT DEFAULT_HIERARCHY
                FROM $system.MDSchema_Dimensions
                WHERE CUBE_NAME = '{0}' AND DIMENSION_NAME = '{1}'", cube, dimension)
            | ObjectType.MEASUREMENT ->
                let parts = name.Split('.')
                let cube = parts.[0]
                let measurement = parts.[1]
                String.Format("SELECT EXPRESSION
                FROM $system.MDSchema_Measures
                WHERE CUBE_NAME = '{0}' AND MEASURE_NAME = '{1}'", cube, measurement)
            | _ ->
                raise (NotImplementedException())
        let tbl = this.CreateDataSet(query.ToString()).Tables.Item(0)
        let rec loop n acc =
            if n > 0 then
                let item = tbl.Rows.Item(n - 1).Item(0).ToString() + Environment.NewLine
                loop (n - 1) (item :: acc)
            else
                acc
        loop tbl.Rows.Count []

    override this.GetNameByTextColumns(searchStr:string, types:ObjectType list, caseSensitive:bool) : string =
        String.Format("SELECT [CUBE_NAME] AS [NAME], 'CUBE'
        FROM $system.MDSchema_Cubes
        WHERE CUBE_SOURCE=1 AND INSTR([CUBE_NAME], '{0}') > 0", searchStr)

    override this.GenerateNameScript(search:string, types:ObjectType list, caseSensitive:bool) : string =
        String.Format("SELECT [CUBE_NAME] + '.' + [MEASURE_NAME] AS [NAME], 'MEASUREMENT'
        FROM $SYSTEM.MDSCHEMA_MEASURES
        WHERE INSTR([MEASURE_NAME], '{0}') > 0 OR INSTR([EXPRESSION], '{0}') > 0", search)

    override this.GenerateSearchScript(search:string, caseSensitive:bool) : string =
        String.Format("SELECT [CUBE_NAME] + '.' + [DIMENSION_NAME] AS [NAME], 'DIMENSION'
        FROM $SYSTEM.MDSCHEMA_DIMENSIONS
        WHERE INSTR([DIMENSION_NAME], '{0}') > 0 OR INSTR([DEFAULT_HIERARCHY], '{0}') > 0", search)

    override this.GetForeignKeyDefinition(constraintName:string) : string =
        raise (NotImplementedException())

    override this.GetPrimaryKeyDefinition(constraintName:string) : string =
        raise (NotImplementedException())

    override this.GetIndexDefinition(constraintName:string) : string =
        raise (NotImplementedException())

    override this.GetSequenceDefinition(sequenceName:string) : string =
        raise (NotImplementedException())

    override this.GetSynonymDefinition(synonymName:string) : string =
        raise (NotImplementedException())

    override this.GetTypeDefinition(typeName:string) : string =
        raise (NotImplementedException())

    override this.GetJobDefinition(jobName:string) : string =
        raise (NotImplementedException())

    override this.GetReportDefinition(reportName:string) : string =
        raise (NotImplementedException())

    override this.GetExtendedProcedureDefinition(procName:string) : string =
        raise (NotImplementedException())

    override this.GetExtendedTriggerDefinition(triggerName:string) : string =
        raise (NotImplementedException())
