import path from 'path'
import fs from 'fs'
import get from 'lodash-es/get.js'
import each from 'lodash-es/each.js'
import evem from './evem.mjs'
import isestr from './isestr.mjs'
import iseobj from './iseobj.mjs'
import ispint from './ispint.mjs'
import cint from './cint.mjs'
import j2o from './j2o.mjs'
import fsCreateFolder from './fsCreateFolder.mjs'
import fsIsFolder from './fsIsFolder.mjs'
import fsDeleteFolder from './fsDeleteFolder.mjs'
import fsWatchFile from './fsWatchFile.mjs'
/**
* 後端nodejs基於檔案內容變更機制提供跨程序EventEmitter
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/fsEvem.test.mjs Github}
* @memberOf wsemi
* @param {String} [fd='./_evps'] 輸入建置事件檔案所在資料夾路徑字串,預設'./_evps'
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {Integer} [opt.timeDetect=50] 輸入偵測佇列間隔時間整數,若基於檔案變更之頻率小於timeDetect,則會發生事件消失問題,單位為毫秒ms,預設為50
* @param {Integer} [opt.timeRewatch=1000] 輸入偵測檔案存在時間整數,單位為毫秒ms,預設為1000
* @example
* need test in nodejs.
*
* // ---- g1.mjs ----
*
* import fsEvem from './src/fsEvem.mjs'
*
* let evf = fsEvem()
*
* evf.on('change', (msgc, msgf) => {
* console.log('recv change g1', msgc)
* })
*
* let n = 0
* setInterval(() => {
* n++
* evf.emit('change', { p1: 'abc', p2: n, p3: 'from g1' })
* }, 2000)
* // recv change g1 { p1: 'abc', p2: 1, p3: 'from g1' }
* // recv change g1 { p1: 'def', p2: 1, p3: 'from g2' }
* // recv change g1 { p1: 'abc', p2: 2, p3: 'from g1' }
* // recv change g1 { p1: 'def', p2: 2, p3: 'from g2' }
* // recv change g1 { p1: 'abc', p2: 3, p3: 'from g1' }
* // recv change g1 { p1: 'def', p2: 3, p3: 'from g2' }
* // recv change g1 { p1: 'abc', p2: 4, p3: 'from g1' }
* // ...
*
* //node --experimental-modules g1.mjs
*
* // ---- g2.mjs ----
*
* import fsEvem from './src/fsEvem.mjs'
*
* let evf = fsEvem()
*
* evf.on('change', (msgc, msgf) => {
* console.log('recv change g2', msgc)
* })
*
* //延遲1s開始
* let n = 0
* setTimeout(() => {
* setInterval(() => {
* n++
* evf.emit('change', { p1: 'def', p2: n, p3: 'from g2' })
* }, 2000)
* }, 1000)
* // recv change g2 { p1: 'abc', p2: 1, p3: 'from g1' }
* // recv change g2 { p1: 'def', p2: 1, p3: 'from g2' }
* // recv change g2 { p1: 'abc', p2: 2, p3: 'from g1' }
* // recv change g2 { p1: 'def', p2: 2, p3: 'from g2' }
* // recv change g2 { p1: 'abc', p2: 3, p3: 'from g1' }
* // recv change g2 { p1: 'def', p2: 3, p3: 'from g2' }
* // recv change g2 { p1: 'abc', p2: 4, p3: 'from g1' }
* // ...
*
* //node --experimental-modules g2.mjs
*
*/
function fsEvem(fd = './_evps', opt = {}) {
let ws = []
//ev
let ev = evem()
//timeDetect
let timeDetect = get(opt, 'timeDetect')
if (!ispint(timeDetect)) {
timeDetect = 50
}
timeDetect = cint(timeDetect)
//timeRewatch
let timeRewatch = get(opt, 'timeRewatch')
if (!ispint(timeRewatch)) {
timeRewatch = 1000
}
timeRewatch = cint(timeRewatch)
//check
if (!fsIsFolder(fd)) {
fsCreateFolder(fd)
}
function watchEvent(evName, cb) {
//fp
let fp = path.resolve(fd, evName)
// console.log('watchEvent fp ', fp)
//fsWatchFile
let evf = fsWatchFile({
timeDetect,
timeRewatch,
})
//監聽檔案內容變更或出現或消失事件
evf.on(fp, (msgFile) => {
//readFileSync
let msgContent = fs.readFileSync(fp, 'utf8')
//check
let _msgContent = j2o(msgContent)
if (iseobj(_msgContent)) {
msgContent = _msgContent
}
//cb
cb(msgContent, msgFile)
})
//push
ws.push({
fp,
evf,
})
}
function unWatchEvent(evName) {
//fp
let fp = path.resolve(fd, evName)
// console.log('watchEvent fp ', fp)
each(ws, (v) => {
if (v.fp === fp) {
v.evf.clear()
}
})
}
function watchEmit(evName, msg) {
//fp
let fp = path.resolve(fd, evName)
// console.log('watchEmit fp ', fp)
//check
if (!isestr(msg)) {
msg = JSON.stringify(msg)
}
//writeFileSync
fs.writeFileSync(fp, msg, 'utf8')
}
function clear() {
each(ws, (v) => {
v.evf.clear()
})
fsDeleteFolder(fd)
}
//save
ev.on = watchEvent
ev.off = unWatchEvent
ev.emit = watchEmit
ev.clear = clear
return ev
}
export default fsEvem