import { modelMap,pptLayout,pptSlideMaster,pptSlideMasterEn } from "./config";
import { parse } from "himalaya";
//import http from '@/api/http.js'
//根据modelId返回组件名,用于component:is
export const countComponentName = (modelId,type)=>{
    let componentName = type==='pre'?'formatPre':'format'

    return `${componentName}${modelMap[modelId]}`
}
//文件检验
export const checkClipboard = (file)=>{
    if (!file) {
      return {msg:'粘贴板为空',status:false}
    }
    if (!file.type.includes('image')) {
      return {msg:'该区域只支持图片格式',status:false}
    }
    return {msg:'',status:true}
}
export const checkClipboardItems = (clipboard)=>{
    for(const Item of clipboard){
        for(const type of Item.types){
            if(type.includes('image')){
                return Item.getType(type)
            }
        }
    }
    return null
}
//全屏
export const setFullscreen = (dom) => {
  if (dom.requestFullscreen) dom.requestFullscreen() 
  else if (dom.mozRequestFullScreen) dom.mozRequestFullScreen() 
  else if (dom.webkitRequestFullScreen) dom.webkitRequestFullScreen()
}
// 判断是否全屏
export const isFullscreen = () => (
  document.mozFullScreen ||                         
  document.webkitIsFullScreen ||       
  document.webkitFullScreen
)
// 退出全屏
export const exitFullscreen = () => {
  if (document.exitFullscreen) document.exitFullscreen()
  else if (document.mozCancelFullScreen) document.mozCancelFullScreen()
  else if (document.webkitCancelFullScreen) document.webkitCancelFullScreen()
}
//根据ppt配置init ppt
export const pptInit = (pptx,LayoutType,lang='ch') => {
    let layout = pptLayout,sliderMaster = lang==='ch'?pptSlideMaster:pptSlideMasterEn
    if(LayoutType!==1){
        layout = { name: "myppt", width: 10, height: LayoutType===2?5.625:7.5 }
        const y = lang==='ch'?0:-0.1
        const h = LayoutType===2?5.625:7.5
        sliderMaster.objects[1] = {image: {x:0,y:y,w:10,h:lang==='ch'?h:h+0.1,path: lang==='ch'?"/static/pptnextimg.png":"/static/ppt_en_bg.png"}}
        sliderMaster.slideNumber = {x:'95%',y:LayoutType===2?'92%':'95%',fontSize:12}
    }
  pptx.defineLayout(layout)
  pptx.layout = layout.name
  pptx.defineSlideMaster(sliderMaster)
return pptx
}
//解析富文本，参考https://github.com/pipipi-pikachu/PPTist/tree/master/src/utils/htmlParser
export const toJson = (html) => {
    const json = parse(html)
    //console.log('json', json)
    return json
}
export const toTextProps = (json) => {
  const slices = []
  let bulletFlag = false
  //剔除掉ul/li里面多余的\n
  for(const item of json){
    if(item.tagName==='ul'||item.tagName==='ol'){
      item.children = item.children.filter(i=>i.type!=='text')
    }
  }
  //console.log('json',json)
  const _parse = (json, baseStyleObj = {}) => {
    for (const item of json) {
      const isBlockTag = 'tagName' in item && ['div', 'li', 'p'].includes(item.tagName)
      if (isBlockTag && slices.length) {
        const lastSlice = slices[slices.length - 1]
        if (!lastSlice.options) lastSlice.options = {}
        lastSlice.options.breakLine = true
      }
      const styleObj = { ...baseStyleObj }
      const styleAttr = 'attributes' in item ? item.attributes.find(attr => attr.key === 'style') : null
      if (styleAttr && styleAttr.value) {
        const styleArr = styleAttr.value.split(';')
        for (const styleItem of styleArr) {
          const [_key, _value] = styleItem.split(': ')
          const [key, value] = [_key ? _key.trim() : '', _value ? _value.trim() : '']
          if (key && value) styleObj[key] = value
        }
      }
      if ('tagName' in item) {
        if (item.tagName === 'em') {
          styleObj['font-style'] = 'italic'
        }
        if (item.tagName === 'strong') {
          styleObj['font-weight'] = 'bold'
        }
        if (item.tagName === 'sup') {
          styleObj['vertical-align'] = 'super'
        }
        if (item.tagName === 'sub') {
          styleObj['vertical-align'] = 'sub'
        }
        if (item.tagName === 'a') {
          const attr = item.attributes.find(attr => attr.key === 'href')
          styleObj['href'] = attr || ''
        }
        if (item.tagName === 'ul') {
          styleObj['list-type'] = 'ul'
        }
        if (item.tagName === 'ol') {
          styleObj['list-type'] = 'ol'
        }
        if (item.tagName === 'li') {
          bulletFlag = true
        }
      }
      if ('tagName' in item && item.tagName === 'br') {
        slices.push({ text: '', options: { breakLine: true } })
      } else if ('content' in item) {
            const transStr = /(&lt;|&gt;|&ldquo;|&rdquo;|&amp;|&lsquo;|&rsquo;|&mdash;|&ge;|&le;|&middot;)/g
            const text = item.content.replace(/\n/g, '').replace(/&nbsp;/g, ' ').replace(transStr, replacer)
            const options = {}

            if (styleObj['font-size']&&styleObj['font-size']!='initial') {
                options.fontSize = parseInt(styleObj['font-size']) * 0.75
            }
            if (styleObj['color']&&styleObj['color']!='initial') {
                options.color = styleObj['color']
            }
            if (styleObj['background-color']&&styleObj['background-color']!='initial') {
                options.highlight = styleObj['background-color']
            }
            if (styleObj['text-decoration-line']) {
                if (styleObj['text-decoration-line'].indexOf('underline') !== -1) {
                    options.underline = {
                        color: options.color || '#000000',
                        style: 'sng',
                    }
                }
                if (styleObj['text-decoration-line'].indexOf('line-through') !== -1) {
                    options.strike = 'sngStrike'
                }
            }
            if (styleObj['text-decoration']) {
                if (styleObj['text-decoration'].indexOf('underline') !== -1) {
                    options.underline = {
                        color: options.color || '#000000',
                        style: 'sng',
                    }
                }
                if (styleObj['text-decoration'].indexOf('line-through') !== -1) {
                    options.strike = 'sngStrike'
                }
            }
            if (styleObj['vertical-align']) {
                if (styleObj['vertical-align'] === 'super') options.superscript = true
                if (styleObj['vertical-align'] === 'sub') options.subscript = true
            }
            if (styleObj['text-align']&&styleObj['text-align']!='initial') options.align = styleObj['text-align']
            if (styleObj['font-weight']) options.bold = styleObj['font-weight'] === 'bold'
            if (styleObj['font-style']) options.italic = styleObj['font-style'] === 'italic'
            if (styleObj['font-family']&&styleObj['font-family']!='initial') options.fontFace = styleObj['font-family']
            if (styleObj['href']) options.hyperlink = {
                url: styleObj['href']
            }
            if (bulletFlag && styleObj['list-type'] === 'ol') {
              options.bullet = { type: 'number', indent: 20 * 0.75 }
              options.paraSpaceBefore = 0.1
              bulletFlag = false
            }
            if (bulletFlag && styleObj['list-type'] === 'ul') {
              options.bullet = { indent: 20 * 0.75 }
              options.paraSpaceBefore = 0.1
              bulletFlag = false
            }
            slices.push({ text, options })
        } else if ('children' in item) _parse(item.children, styleObj)
    }
  }
  _parse(json)
  //console.log('slice', slices)
  return slices
}
//将text中被转义的字符转义回来,如:a<b 在富文本内会被转义成 a&lt;b
const replacer = (_, p1) => {
    return {
        "&lt;": "<",
        "&gt;": ">",
        "&ldquo;": "“",
        "&rdquo;": "”",
        "&amp;":"&",
        "&lsquo;":"‘",
        "&rsquo;":"’",
        "&mdash;":'——',
        "&ge;":'≥',
        "&le;":'≤',
        "&middot;":'·'
    } [p1]
}
//根据字符串的字节长,在指定位置换行
export const getStrSize = (str,count=60)=>{
    let total = 0,strcount=0,newStr = ''
    for(let i=0;i<str.length;i++){
        let chartCode = str.charCodeAt(i)
        if(chartCode>255){
            total+=2
            strcount+=2
        }else{
            total+=1
            strcount+=1
        }
        newStr+=str[i]
        if(strcount>=count){
            newStr+='<br/>'
            strcount=0
        }
    }
    return {total,newStr}
}
export const countStrSize = (str)=>{
    let strCount = 0
    for(let i=0;i<str.length;i++){
        let chartCode = str.charCodeAt(i)
        if(chartCode>255) strCount+=2
        else strCount+=1
    }
    return strCount
}
//计算图像的真实尺寸(object-fit:scale-down)
export const getImgRealSize = ({imgWidth,imgHeight,naturalWidth,naturalHeight})=>{
    let ratio = naturalWidth/naturalHeight
    let width = imgHeight*ratio,height=imgHeight
    if(width>imgWidth){
        width = imgWidth
        height = imgWidth/ratio
    }
    return {width,height}
}
//格式化目录数组数据,返回树形数据结构格式
export const changeCatalogArr = (arr)=>{
    let tempArr = arr.map((item)=>{
        item.label = item.GroupName
        item.copyIconShow = false
        item.isShare = item.IsShare
        item.nodeKeyId = item.GroupId
        item.children = item.PptList?item.PptList.map((i)=>{
          i.nodeKeyId = 'ppt'+i.PptId //避免和目录id重复的情况
          i.label = i.Title
          i.catalogId = item.GroupId
          i.isShare = i.IsSingleShare
          i.copyIconShow = false
          i.isTrans = i.ReportId===0?false:true
          return i
        }):[]
        return item
      })
    return tempArr
}
// 生成随机码
 export const createRandomCode = (len = 8) => {
  const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`
  const maxLen = charset.length
  let ret = ''
  for (let i = 0; i < len; i++) {
    const randomIndex = Math.floor(Math.random() * maxLen)
    ret += charset[randomIndex]
  }
  return ret
}
//计算各个版式下,文本框占据的真实宽度
//基准:编辑页ppt-item的最大宽高:w:900px;h:630
export const getTextContentSize = (model,position)=>{
    const modelMapWidth = {
        1:{
          1:[]//版式1没有文本框
        },
        //顺序是 .total-wrap -> wrap -> .editor-wrap
        2:{//modelId
          1:[1,0.6,0.9],//position
          2:[1,0.4,0.9]
        },
        3:{
          1:[1,0.5,1,0.9],
          2:[1,0.5,1,0.9],
          3:[1,0.5,1,0.9]
        },
        4:{
          1:[1,0.5,1,0.9],
          2:[1,0.5,1,0.9],
          3:[1,0.5,1,0.9],
          4:[1,0.5,1,0.9]
        },
        5:{
          1:[],2:[],3:[],4:[]//版式5没有文本框
        },
        6:{
          1:[1,1,0.9]
        },
        7:{
          1:[],2:[]
        },
        8:{
          1:[1,1,0.9],
          2:[1,1,0.9]
        },
        9:{
          1:[1,1,0.5,0.9],
          2:[1,1,0.5,0.9],
          3:[1,1,0.9]
        }
    }
    const modelMapHeight = {
        1:{
          1:[]
        },
        //顺序是 .total-wrap -> wrap -> .editor-wrap
        2:{
          1:[0.86,1,0.8],
          2:[0.86,1,0.8]
        },
        3:{
          1:[0.86,1,0.5,0.84],
          2:[0.86,1,0.5,0.84],
          3:[0.86,1,0.84]
        },
        4:{
          1:[0.86,1,0.5,0.84],
          2:[0.86,1,0.5,0.84],
          3:[0.86,1,0.5,0.84],
          4:[0.86,1,0.5,0.84]
        },
        5:{
          1:[],2:[],3:[],4:[]
        },
        6:{1:[0.86,1,0.9]},
        7:{1:[],2:[]},
        8:{
          1:[0.86,0.7,0.9],
          2:[0.86,0.3,0.8]
        },
        9:{
          1:[0.86,0.7,1,0.9],
          2:[0.86,0.7,1,0.9],
          3:[0.86,0.3,0.8]
        }
    }
    const baseWidth=900,baseHeight=630
    const width = modelMapWidth[model][position].reduce((pre,curr)=>{
        return pre*curr
    },baseWidth)
    const height = modelMapHeight[model][position].reduce((pre,curr)=>{
        return pre*curr
    },baseHeight)
    return {width:width-20+'px',height:height-20+'px'}
}
// svg转base64图片，参考：https://github.com/scriptex/svg64
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
const PREFIX = 'data:image/svg+xml;base64,'
const utf8Encode = (string) => {
  string = string.replace(/\r\n/g, '\n')
  let utftext = ''
  for (let n = 0; n < string.length; n++) {
    const c = string.charCodeAt(n)
    if (c < 128) {
      utftext += String.fromCharCode(c)
    }
    else if (c > 127 && c < 2048) {
      utftext += String.fromCharCode((c >> 6) | 192)
      utftext += String.fromCharCode((c & 63) | 128)
    }
    else {
      utftext += String.fromCharCode((c >> 12) | 224)
      utftext += String.fromCharCode(((c >> 6) & 63) | 128)
      utftext += String.fromCharCode((c & 63) | 128)
    }
  }
  return utftext
}
const encode = (input) => {
  let output = ''
  let chr1, chr2, chr3, enc1, enc2, enc3, enc4
  let i = 0
  input = utf8Encode(input)
  while (i < input.length) {
    chr1 = input.charCodeAt(i++)
    chr2 = input.charCodeAt(i++)
    chr3 = input.charCodeAt(i++)
    enc1 = chr1 >> 2
    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
    enc4 = chr3 & 63
    if (isNaN(chr2)) enc3 = enc4 = 64
    else if (isNaN(chr3)) enc4 = 64
    output = output + characters.charAt(enc1) + characters.charAt(enc2) + characters.charAt(enc3) + characters.charAt(enc4)
  }
  return output
}
export const svg2Base64 = (element) => {
  const XMLS = new XMLSerializer()
  const svg = XMLS.serializeToString(element)
  return PREFIX + encode(svg)
  //return PREFIX + new http.Base64().encode(svg)
}
//计算图层元素的宽高是否在最大值(一般是layers的宽高),最小值(一般是width:25,height:25)内,返回一个合法的数值
export const getBoundary = (value=0,base=0,max=0)=>{
  if(value<=base) return base
  else if(value>=max) return max
  else return value
}
//计算图层元素:直线拖拽的坐标
export const getLineScaleInfo = (point,el,type)=>{
  const {left,top,width,height,start,end} = el
  const {moveX,moveY} = point
  let scaleInfo = {left:left,top:top,width:width,height:height,start:start,end:end}
  // 线条起点和终点在编辑区域中的位置
  let startX = left + start[0]
  let startY = top + start[1]
  let endX = left + end[0]
  let endY = top + end[1]
  if(type==='START'){
    startX = startX + moveX
    startY = startY + moveY
  }
  else if(type==='END'){
    endX = endX + moveX
    endY = endY + moveY
  }
  // 计算更新起点和终点基于自身元素位置的坐标
  const minX = Math.min(startX, endX)
  const minY = Math.min(startY, endY)
  const maxX = Math.max(startX, endX)
  const maxY = Math.max(startY, endY)
  const tempStart = [0, 0]
  const tempEnd = [maxX - minX, maxY - minY]
  if (startX > endX) {
    tempStart[0] = maxX - minX
    tempEnd[0] = 0
  }
  if (startY > endY) {
    tempStart[1] = maxY - minY
    tempEnd[1] = 0
  }
  let scaleWidth = Math.abs(tempEnd[0] - tempStart[0]),
      scaleHeight = Math.abs(tempEnd[1] - tempStart[1]) 
  scaleInfo = {
    left:Math.max(minX,0),
    top:Math.max(minY,0),
    width:scaleWidth<25?25:scaleWidth,
    height:scaleHeight<25?25:scaleHeight,
    start:tempStart,
    end:tempEnd
  }
  return scaleInfo
}
//计算元素应该缩放的比例
export const calcScale = (oldShap,newShap)=>{
  let scale = {x:1,y:1}
  scale.x = newShap.w/oldShap.w
  scale.y = newShap.h/oldShap.h
  return scale
}
//计算元素的百分比化单位
export const caclShapePercentage = (layer,el)=>{
  const {layerWidth,layerHeight} = layer
  const {left,top,width,height} = el
  const percentageLeft = left/layerWidth
  const percentageTop = top/layerHeight
  const percentageWidth = width/layerWidth
  const percentageHeight = height/layerHeight
  return {percentageLeft,percentageTop,percentageWidth,percentageHeight}
}
//计算图层元素的真实宽高
export const caclShapeRealSize = (layer,shape)=>{
  return {realWidth:shape.percentageWidth*layer.width,realHeight:shape.percentageHeight*layer.height}
}
//将rgba转为hex+透明度的格式
//rgba(91,155,213,0.44) -> {color: "#5b9bd5",transparency: 56}
const parseRgbaColor = (color) => {
  const arr = color.match(/(\d(\.\d+)?)+/g) || [];
  const res = arr.map((s) => parseInt(s, 10));
  return {
    r: res[0],
    g: res[1],
    b: res[2],
    a: parseFloat(arr[3]),
  } 
}
const toHex = (n) => `${n > 15 ? '' : 0}${n.toString(16)}`;
const toHexString = (colorObj) => {
   const { r, g, b,} = colorObj;
   return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
 }
export const rgbaToHex = (rgba) => {
    const colorObj = parseRgbaColor(rgba);
    return {color:toHexString(colorObj),transparency:(1-colorObj.a)*100}
};
//获取shape的格式数据,写入ppt
export const getShapeOptions = (el,position,scale)=>{
  let options = {
    x:position.x+'%',
    y:position.y+'%',
    w:position.w+'%',
    h:position.h+'%',
  }
  if(el.type==='shape'){
    options.fill = rgbaToHex(el.fill)
    
    if(el.shapeType==='Rect'){
        options.points=[
            {x:0,y:0,moveTo:true},
            {x:position.w+'%',y:0},
            {x:position.w+'%',y:position.h+'%'},
            {x:0,y:position.h+'%'},
            {close:true}
          ]
    }
    options.line = {
      type:'solid',
      color:rgbaToHex(el.outline.color).color,
      transparency:rgbaToHex(el.outline.color).transparency,
      width:el.outline.width,
      dashType:el.outline.style === 'solid' ? 'solid' : 'dash',
    }
  }
  if(el.type==='line'){
    const width = Math.max(el.start[0], el.end[0])
    const height = Math.max(el.start[1], el.end[1])
    //px->英尺 1英尺≈100px（在ppt-width为10英尺的情况下）
    //906:628.6(编辑页的宽高比) --> 1008:705.6 相当于扩大了1.13倍
    options.w = (width*scale.x/100)>10?10:width*scale.x/100
    options.h = (height*scale.y/100)>10?10:height*scale.y/100
    options.points = [
      {x:Math.min(el.start[0]*scale.x/100,10),y:Math.min(el.start[1]*scale.y/100,10),moveTo:true},
      {x:Math.min(el.end[0]*scale.x/100,10),y:Math.min(el.end[1]*scale.y/100,10)}
    ]
    options.line={
      type:'solid',
      color:rgbaToHex(el.color).color,
      transparency:rgbaToHex(el.color).transparency,
      width:el.strokeWidth*0.75,//不缩小下的话线太粗了
      dashType:el.style==='solid'?'solid':'dash',
      beginArrowType: el.points[0] ? 'triangle' : 'none',
      endArrowType: el.points[1] ? 'triangle' : 'none',
    }
  }
  return options
}
//转换table的数据格式，写入ppt
export const getTableData = (data)=>{
  //data:[{m:'表格数据',mc:{rs:2,cs:1}}] -> [{text:'表格数据',options:{rowspan:2,colspan:1}}]
  const tableData = []
  for(let i=0;i<data.length;i++){
    const row = data[i]
    const _row =[]
    for(let j=0;j<row.length;j++){
      const cell = row[j]
      let cellOptions = {
        colspan:cell.mc.cs===0?1:cell.mc.cs,
        rowspan:cell.mc.rs===0?1:cell.mc.rs
      }
        _row.push({
          text:cell.m,
          options:cellOptions
        })

    }
    if(_row.length) tableData.push(_row)
  }
  return tableData
}
//转换pptDate的格式,中文:yyyy年MM月;英文:yyyy.MM
export const formatPPTDate = (lang,date)=>{
  if(lang!=='en') return date
  let str = date.replace('年','.')
  str = str.replace('月','')
  return str
}

//检查pptPage.elements的格式,返回所有合法的elements
export const checkPPTpageElemant = (page) =>{
  const {elements} = page
  let legalElements = []
  elements.forEach(el=>{
    checkAttribute(el)&&legalElements.push(el)
  })
  return legalElements
}
//属性检查
export const checkAttribute = (el)=>{
  if(el.type==='chart'){
    return el.chartId
  }
  if(el.type==='image'){
    return el.src
  }
  if(el.type==='text'){
    return el.content&&el.richContent
  }
  if(el.type==='sheet'){
    return el.sheetId
  }
}
//更新chartInfoMapItem
export const getChartInfo = (options)=>{
  let item = {chartInfoId:0,chartTitle:'',MyChartClassifyId:''}
  if(options instanceof Object){
    item.chartInfoId = options.chartInfoId
    item.chartTitle = options.chartTitleCN
    item.MyChartClassifyId = options.MyChartClassifyId
  }
  return item
}
//计算layer-menu相对于menu的位置
export const getContextMenuPos = (layerId) =>{
    const layerBoundingClientRect = document.querySelector(`#${layerId}`).getBoundingClientRect()
    const menuBoundingClientRect = document.querySelector(`#menu`).getBoundingClientRect()
    return {clientX:menuBoundingClientRect.x - layerBoundingClientRect.x,
            clientY:menuBoundingClientRect.y - layerBoundingClientRect.y,}
}
