Imports System.Web
Imports System.Text
Imports System.Configuration

Public Class clsHTMLThread
    Private _SQLID As Integer
    Private _SQLName As String
    Private _MainSQL As clsSQLAndCacheName
    Private _CountSQL As clsSQLAndCacheName
    Private _FunctionNote As XElement
    Private _ControlID As String
    Private _CacheLife As XrCache.CacheLifeType
    Private _CacheDependOf As String
    Private _OpenSecondCache As Boolean
    Private _CacheItem As clsCache

    Private Structure PagingList
        Dim ReplaceString As String
        Dim PagingString As String
    End Structure

    Public Property CacheItem() As clsCache
        Get
            Return _CacheItem
        End Get
        Set(ByVal value As clsCache)
            _CacheItem = value
        End Set
    End Property
    Public Property SQLID() As Integer
        Get
            Return _SQLID
        End Get
        Set(ByVal value As Integer)
            _SQLID = value
        End Set
    End Property
    Public Property SQLName() As String
        Get
            Return _SQLName
        End Get
        Set(ByVal value As String)
            _SQLName = value
        End Set
    End Property
    Public Property MainSQL() As clsSQLAndCacheName
        Get
            Return _MainSQL
        End Get
        Set(ByVal value As clsSQLAndCacheName)
            _MainSQL = value
        End Set
    End Property
    Public Property CountSQL() As clsSQLAndCacheName
        Get
            Return _CountSQL
        End Get
        Set(ByVal value As clsSQLAndCacheName)
            _CountSQL = value
        End Set
    End Property
    Public Property FunctionNote() As XElement
        Get
            Return _FunctionNote
        End Get
        Set(ByVal value As XElement)
            _FunctionNote = value
        End Set
    End Property
    Public Property ControlID() As String
        Get
            Return _ControlID
        End Get
        Set(ByVal value As String)
            _ControlID = value
        End Set
    End Property
    Public Property CacheLife() As XrCache.CacheLifeType
        Get
            Return _CacheLife
        End Get
        Set(ByVal value As XrCache.CacheLifeType)
            _CacheLife = value
        End Set
    End Property

    Public Property CacheDependOf() As String
        Get
            Return _CacheDependOf
        End Get
        Set(ByVal value As String)
            _CacheDependOf = value
        End Set
    End Property
    Public Property OpenSecondCache() As Boolean
        Get
            Return _OpenSecondCache
        End Get
        Set(ByVal value As Boolean)
            _OpenSecondCache = value
        End Set
    End Property

    Public Function UpdateMainCache() As clsHTML
        Dim returnHTML As New clsHTML
        Dim strTitle As String = ""
        Dim strKeyWord As String = ""
        Dim strDescription As String = ""

        Dim AllHTML As New StringBuilder
        For Each n In FunctionNote.Elements
            AllHTML.Append(n.ToString)
        Next

        Dim mPageSize As Integer = 0
        Dim mPageCount As Integer = 0
        Dim mRecordCount As Integer = -1 '总记录数
        Integer.TryParse(FunctionNote.Attribute("pagesize").Value, mPageSize)
        Integer.TryParse(FunctionNote.Attribute("pagecount").Value, mPageCount)
        Dim iTable As Data.DataTable = Nothing
        Dim mPagingList As New List(Of PagingList)
        Using mConn As New Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("XrenCRMConnString").ConnectionString)
            mConn.Open()
            Dim mCMD As New Data.SqlClient.SqlCommand
            mCMD.Connection = mConn
            mCMD.CommandText = MainSQL.SQL
            Dim mDA As New Data.SqlClient.SqlDataAdapter(mCMD)
            Dim mDT As New Data.DataSet
            Try
                mDA.Fill(mDT)
            Catch ex As Exception
                mConn.Close()
                Return Nothing
            End Try
            If mDT.Tables.Count > 0 Then
                iTable = mDT.Tables(0)
            End If
            If mPageSize > 0 Then
                mCMD.CommandText = CountSQL.SQL
                mRecordCount = CType(mCMD.ExecuteScalar, Integer)
                mPagingList = CreatePagingLink(mRecordCount, mPageSize, mPageCount)
            End If

            mCMD.CommandText = "select TOP 1 PageTitle,KeyWords,Description from SiteSEO where BindID =" & SQLID.ToString & " AND BindType=1"
            Dim mRD As Data.SqlClient.SqlDataReader
            mRD = mCMD.ExecuteReader
            If mRD.Read Then
                strTitle = Base64DecryptData(mRD.GetValue(0).ToString)
                strKeyWord = Base64DecryptData(mRD.GetValue(1).ToString)
                strDescription = Base64DecryptData(mRD.GetValue(2).ToString)
            End If
            mRD.Close()
            mConn.Close()
        End Using
        Dim mDatas = (From d In FunctionNote.Elements("data") _
                     Select d).ToList
        Dim mLoop As XElement = FunctionNote.Element("loop")
        Dim mLoopDataHtml As String = mLoop.Element("data").Value

        Dim strField As String = ""
        Dim LoopHtml As New StringBuilder
        If iTable IsNot Nothing AndAlso iTable.Rows.Count > 0 Then
            For i As Integer = 0 To iTable.Rows.Count - 1
                Dim rLoop As String = mLoopDataHtml
                For j As Integer = 0 To iTable.Columns.Count - 1
                    strField = "<field name=""" & iTable.Columns(j).ColumnName & """ />"
                    rLoop = rLoop.Replace(strField, iTable.Rows(i)(j))
                    strTitle = strTitle.Replace(strField, iTable.Rows(i)(j))
                    strKeyWord = strKeyWord.Replace(strField, iTable.Rows(i)(j))
                    strDescription = strDescription.Replace(strField, iTable.Rows(i)(j))
                Next
                LoopHtml.Append(rLoop)
            Next
            returnHTML.Title = strTitle
            returnHTML.KeyWords = strKeyWord
            returnHTML.Description = strDescription
        End If
        AllHTML = AllHTML.Replace(mLoop.ToString, LoopHtml.ToString)
        For Each d In mDatas
            AllHTML = AllHTML.Replace(d.ToString, d.Value)
        Next
        If mPagingList IsNot Nothing AndAlso mPagingList.Count > 0 Then
            For Each p In mPagingList
                AllHTML = AllHTML.Replace(p.ReplaceString, p.PagingString)
            Next
            AllHTML.Append(JavaScript)
        End If
        returnHTML.HTML = AllHTML.ToString

        Select Case CacheLife
            Case 0
                Return returnHTML
            Case 1
                Web.HttpRuntime.Cache.Insert(MainSQL.CacheName, returnHTML, Nothing, Now.AddMinutes(CType(CacheDependOf, Integer)), Web.Caching.Cache.NoSlidingExpiration, CacheItem.CachePriority, New Web.Caching.CacheItemRemovedCallback(AddressOf XrCache.OnCacheRemove))
            Case 2
                Web.HttpRuntime.Cache.Insert(MainSQL.CacheName, returnHTML, Nothing, Web.Caching.Cache.NoAbsoluteExpiration, New System.TimeSpan(0, CType(CacheDependOf, Integer), 0), CacheItem.CachePriority, New Web.Caching.CacheItemRemovedCallback(AddressOf XrCache.OnCacheRemove))
            Case 3
                Dim mFiles() As String = Split(CacheDependOf, ",")
                For i As Integer = 0 To mFiles.Count - 1
                    mFiles(i) = Web.HttpContext.Current.Request.PhysicalApplicationPath & "CacheFile\" & mFiles(i)
                Next
                Web.HttpRuntime.Cache.Insert(MainSQL.CacheName, returnHTML, New Web.Caching.CacheDependency(mFiles), Now.AddDays(7), Web.Caching.Cache.NoSlidingExpiration, CacheItem.CachePriority, New Web.Caching.CacheItemRemovedCallback(AddressOf XrCache.OnCacheRemove))
        End Select

        '主缓存更新后，更新二级缓存
        If OpenSecondCache Then
            SyncLock (GetType(XrCache))
                Web.HttpRuntime.Cache.Insert("SecCache_" & MainSQL.CacheName, returnHTML, Nothing, Web.Caching.Cache.NoAbsoluteExpiration, Web.Caching.Cache.NoSlidingExpiration, CacheItem.CachePriority, Nothing)
            End SyncLock
        End If
        CacheItem.IsUpdate = False
        XrCache.SaveCacheItem(CacheItem, MainSQL.CacheName)
        Return returnHTML
    End Function
    ''' <summary>
    ''' 获取当前页码
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ThisPage() As Integer
        Get
            Dim mPage As Integer = 0
            Integer.TryParse(HttpContext.Current.Request(ControlID & "_Page"), mPage)
            Return mPage
        End Get
    End Property
    Private Function JavaScript() As String
        Dim strURL As String = HttpContext.Current.Request.RawUrl
        Dim mScript As New StringBuilder
        mScript.AppendLine("<script language=""javascript"" type=""text/javascript"">")
        mScript.AppendLine("function SubPage" & ControlID & "(PageNum){")
        mScript.AppendLine(" document.getElementById('" & ControlID & "_Page').value=PageNum;")
        mScript.AppendLine(" var mForm = document.forms[0];")
        mScript.AppendLine(" mForm.action = '" & strURL & "';")
        mScript.AppendLine(" mForm.submit();")
        mScript.AppendLine("}")
        mScript.AppendLine("</script>")
        mScript.AppendLine("<input id=""" & ControlID & "_Page"" type=hidden name=""" & ControlID & "_Page"" value=""" & ThisPage & """>")
        Return mScript.ToString
    End Function


    Private Function CreatePagingLink(ByVal RecordCount As Integer, ByVal PageSize As Integer, ByVal PagingCount As Integer) As List(Of PagingList)
        Dim mList As New List(Of PagingList)
        Dim strNumPage As New StringBuilder("")
        Dim mWhilePart As Integer = 0
        Dim MinPage As Integer = 0
        Dim MaxPage As Integer = 0
        Dim FirstPage As Integer = ThisPage
        If FirstPage = 0 Then FirstPage = 1
        Dim mPageCount As Integer = 0 '页总数
        mPageCount = SumPage(RecordCount, PageSize) '计算总页数
        Dim mFuncionName As String = "SubPage" & ControlID
        '生成页码链接
        If PageSize >= mPageCount Then
            MinPage = 1
            MaxPage = mPageCount
        Else
            mWhilePart = SumMultiplier(mPageCount, PagingCount)
            MinPage = (mWhilePart - 1) * PageSize + 1
            MaxPage = mWhilePart * PageSize
            If MaxPage > mPageCount Then MaxPage = mPageCount
        End If
        For i As Integer = MinPage To MaxPage
            If ThisPage <> i Then
                strNumPage.Append("<a onclick = """ & mFuncionName & "('" & i.ToString & "');"">" & i.ToString & "</a>")
            Else
                strNumPage.Append("<a id=""thisPage"" onclick = """ & mFuncionName & "('" & i.ToString & "');"">" & i.ToString & "</a>")
            End If
        Next
        mList.Add(New PagingList With {.PagingString = strNumPage.ToString, .ReplaceString = "<Page:页码>"})
        If mWhilePart > 1 Then
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('1');>1...</a>", .ReplaceString = "<Page:首页>"})
        Else
            mList.Add(New PagingList With {.PagingString = "", .ReplaceString = "<Page:首页>"})
        End If
        If MaxPage < mPageCount Then
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('" & mPageCount.ToString & "');>..." & mPageCount.ToString & "</a>", .ReplaceString = "<Page:尾页>"})
        Else
            mList.Add(New PagingList With {.PagingString = "", .ReplaceString = "<Page:尾页>"})
        End If
        If FirstPage > 1 Then
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('" & (FirstPage - 1).ToString & "');"">上一页</a>", .ReplaceString = "<Page:上一页>"})
        Else
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('" & FirstPage.ToString & "');"">上一页</a>", .ReplaceString = "<Page:上一页>"})
        End If
        If FirstPage >= mPageCount Then
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('" & mPageCount.ToString & "');"">下一页</a>", .ReplaceString = "<Page:下一页>"})
        Else
            mList.Add(New PagingList With {.PagingString = "<a onclick = """ & mFuncionName & "('" & (FirstPage + 1).ToString & "');"">下一页</a>", .ReplaceString = "<Page:下一页>"})
        End If
        Return mList
    End Function

    Private Function TranOperator(ByVal SQLOperator As Integer) As String
        Select Case SQLOperator
            Case 0
                Return " LIKE "
            Case 1
                Return " > "
            Case 2
                Return " = "
            Case 3
                Return " < "
            Case 4
                Return ">="
            Case 5
                Return "<="
            Case Else
                Return ""
        End Select
    End Function
    ''' <summary>
    ''' 计算页码
    ''' </summary>
    ''' <param name="intCount">记录数</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function SumPage(ByVal intCount As Integer, ByVal PageSize As Integer) As Integer
        If intCount <= PageSize Then Return 1
        Dim iPage As Integer = intCount \ PageSize
        Dim dPage As Single = intCount / PageSize
        If dPage > iPage Then
            Return iPage + 1
        Else
            Return iPage
        End If
    End Function
    ''' <summary>
    ''' 计算当前页码在第几个显示区间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function SumMultiplier(ByVal ingPageCount As Integer, ByVal PagingCount As Integer) As Integer
        If ThisPage <= PagingCount Then Return 1
        '计算区间总数
        Dim AllPage As Integer
        Dim iPage As Integer = ingPageCount \ PagingCount
        Dim dPage As Single = ingPageCount / PagingCount
        If dPage > iPage Then
            AllPage = iPage + 1
        Else
            AllPage = iPage
        End If

        Dim ThisPart As Integer = 0
        For i As Integer = 1 To AllPage
            If i * PagingCount >= ThisPage Then
                ThisPart = i
                Exit For
            End If
        Next
        Return ThisPart
    End Function
    Public Shared Function Base64DecryptData(ByVal encryptedtext As String) As String
        Dim strReturn As String = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(encryptedtext))
        Return strReturn.Replace("/&/&", "+")
        'Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedtext)
        'Return System.Text.Encoding.Unicode.GetString(encryptedBytes)
    End Function
End Class
